【问题标题】:jquery .getscript() callback when script is fully loaded and executedjquery .getscript() 脚本完全加载并执行时的回调
【发布时间】:2013-01-11 23:42:49
【问题描述】:

来自 jquery api 页面 http://api.jquery.com/jQuery.getScript/

成功回调

一旦脚本被加载但不一定被执行,回调就会被触发。

$.getScript("test.js", function() {
    foo();
});

如果foo()函数依赖于test.js,则无法成功执行。

我在 google map api 中看到过类似的情况,但在这种情况下,您可以在 ajax 脚本 url 中指定回调函数。但是一般来说有没有明显的方法可以等到ajax脚本执行后再做回调?

【问题讨论】:

  • 您收到错误消息了吗?
  • 函数未定义。
  • 还有“未定义不是函数”
  • 如果您使用的是 chrome 或 firefox;如果您将console.log('xxxx'); 放入回调函数而不是foo();,它是否会回显到控制台
  • 实际上,在大多数情况下,回调会在脚本执行后触发 - 请参阅 this questionissue raised on jQuery's GitHub。你需要弄清楚你的情况有什么独特之处。另外@richb01,您的网站已关闭。

标签: jquery ajax


【解决方案1】:

我知道这是一个老问题,但我认为包含“完成”的两个答案都没有得到其所有者的解释,它们实际上是最好的答案。

投票最多的答案要求使用“async:false”,这反过来会创建一个不是最佳的同步调用。另一方面,从 1.5 版(可能更早?)开始,jquery 引入了 promise 和 promise 处理程序,在这种情况下,我们尝试异步加载脚本并等待它完成运行。

定义为getScript documentation的回调

一旦脚本被加载但不一定被执行,回调就会被触发。

您需要寻找的是承诺的行为方式。在这种情况下,当您正在寻找一个异步加载的脚本时,您可以使用“then”或“done” 看看this thread,它很好地解释了差异。

只有在 promise 被解决时才会调用 done。在我们的例子中,当脚本成功加载并完成运行时。所以基本上在你的代码中这意味着:

$.getScript("test.js", function() {
    foo();
});

应该改为:

$.getScript("test.js").done(function(script, textStatus) {
    console.log("finished loading and running test.js. with a status of" + textStatus);
});

【讨论】:

  • 问题是success、.then、.done等都是在HTTP调用完成时调用,而不是在获取的脚本可以执行时调用。异步问题的问题在于它们适用于某些人而不适用于其他人,因此您的结果由“适用于我,显然您只是不理解承诺”的答案所主导,这就是我们在这里所拥有的。好吧,这对我不起作用。 :)
【解决方案2】:

$.getScript(...) + setInterval(...) 为我工作:

$.getScript('https://www.google.com/recaptcha/api.js')
  .done(function() {
    var setIntervalID = setInterval(function() {
      if (window.grecaptcha) {
        clearInterval(setIntervalID);
        console.log(window.grecaptcha);
        letsWorkWithWindowDotGreptcha();
      };
    }, 300);
  });


  function letsWorkWithWindowDotGreptcha() {
    // window.greptcha is available here....
  }

一旦定义了我们要查找的variable(在我的情况下为window.grecaptcha,我可以调用closure function,它可以是abstracted out

祝你好运……

【讨论】:

  • 我会说这是最好的解决方案,而我不喜欢在我的脚本中处理setInterval(...)
【解决方案3】:

你可以使用ajax

jQuery.ajax({
        async:false,
        type:'GET',
        url:script,
        data:null,
        success:callback,
        dataType:'script'
    });

Async 为 false,因为你想加载并执行脚本,之后在成功回调中你可以调用你的函数 foo()

【讨论】:

  • 还是说明脚本中的前置函数还没有执行:(
  • 我使用此代码并为我工作,我遇到了与您相同的问题。但是是因为get脚本有一个回调函数,如果请求成功就会执行,但是代码还没有。
  • 非常感谢,我也在文档中看到了这一点“从 jQuery 1.8 开始,不推荐使用 async: false 和 jqXHR ($.Deferred);您必须使用成功/错误/完成回调选项而不是 jqXHR 对象的相应方法,例如 jqXHR.done() 或已弃用的 jqXHR.success()。"不确定是否相关。
  • 不能解决问题。它使 HTTP 调用异步,但脚本仍未在 success/.then 中加载。
【解决方案4】:
$.getScript( "ajaxFile/myjs.js" )
.done(function( s, Status ) {
    console.warn( Status );
})
.fail(function( jqxhr, settings, exception ) {
    console.warn( "Something went wrong"+exception );
});

【讨论】:

  • 请试着解释一下你的代码。 Stack Overflow 不是一个获得“只是解决方案”的网站,目的也是建立知识。这就是为什么我认为纯代码的答案很少值得赞成。
  • 回调方法在 jQuery 中已弃用,延迟处理程序是经过测试和支持的方法,用于将行为附加到异步加载。也就是说,我不确定他们是否保证脚本会在调用时执行。
【解决方案5】:

我今天遇到了同样的问题,并提出了一个基于承诺和间隔计时器的解决方案:

$.getScript("test.js", function() {
    var $def = $.Deferred();
    if (typeof foo === 'undefined') { // "foo" isn't available
        var attempts = 0;
        // create an interval
        // that will check each 100ms if the "foo" function
        // was loaded
        var interval = setInterval(function() {
            if (typeof foo !== 'undefined') { // loaded
                window.clearInterval(interval);
                $def.resolve();
            }
            // after X unsuccessfull attempts, abort the operation
            else if (attempts >= 100) {
                window.clearInterval(interval);
                $def.reject('Something went wrong');
            }

            attempts++;
        }, 100);
    }
    else { // "foo" is available
        $def.resolve();
    }
    return $def.promise();
}).then(function() {
    // at this point "foo()" is definitely available.
}).fail(function() {
    // deal with the failure
});

想法是您加载一个给定的脚本,该脚本将公开一些仍然不存在的变量(您的问题示例中的foo 函数),因此在getScript 加载脚本后,您检查此变量是否存在,如果不存在,则创建一个间隔,该间隔将持续检查变量是否可用,并且仅当满足此条件时,您才会解决承诺。

【讨论】:

    【解决方案6】:

    正如提到的thendone$.getScript 回调在脚本被加载但未执行时触发,可能是很早......间隔可能是解决这个问题的一种方法,但在我看来它似乎不是很优雅.

    我的解决方案是在异步加载的脚本中触发一个事件,例如:

    jQuery( document ).trigger( 'loadedeventsjs' );
    

    在我的主脚本中,我可以像这样绑定到该事件:

    jQuery( document ).on( 'loadedeventsjs', function() {
    
        jQuery( '#mainmenu_wrapper' ).on( 'swiperight', menuout );
    
    } );
    

    【讨论】:

      【解决方案7】:

      恐怕该解决方案需要轮询依赖项。或者,脚本需要包装在像 AMD 这样的预定义回调中。

      【讨论】:

        【解决方案8】:

        $getScript 像这样使用

        $.getScript( "js/jquery.raty.min.js" )
            .done(function( script, textStatus ) {
                  console.log( textStatus );
                 }
                  });
        

        这对我来说很好用

        【讨论】:

        • 请试着解释一下你的代码。 Stack Overflow 不是一个获取“解决方案”的网站,目的也是为了积累知识。
        • 我认为你没有抓住重点。回调需要使用您刚刚加载的脚本中定义的内容。
        猜你喜欢
        • 1970-01-01
        • 2013-08-09
        • 2014-02-07
        • 2015-12-24
        • 2016-02-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多