Javascript 当所有脚本通过$.getScript完成加载时调用处理程序

Javascript 当所有脚本通过$.getScript完成加载时调用处理程序,javascript,jquery,ajax,Javascript,Jquery,Ajax,假设我们通过$加载一组脚本。getScript: $.getScript( 'js/script1.js' ); $.getScript( 'js/script2.js' ); $.getScript( 'js/script3.js' ); 现在,我想在所有这些脚本加载完毕后调用一个处理程序。我尝试为全局绑定一个处理程序。根据,如果不再处理Ajax请求,将触发ajaxStop全局事件 $( document ).ajaxStop( handler ); 但它不起作用(不调用处理程序) 现场演

假设我们通过
$加载一组脚本。getScript

$.getScript( 'js/script1.js' );
$.getScript( 'js/script2.js' );
$.getScript( 'js/script3.js' );
现在,我想在所有这些脚本加载完毕后调用一个处理程序。我尝试为全局绑定一个处理程序。根据,如果不再处理Ajax请求,将触发
ajaxStop
全局事件

$( document ).ajaxStop( handler );
但它不起作用(不调用处理程序)

现场演示:


我怎样才能做到这一点呢?

我对这个问题做了进一步的探讨,实际上跨域脚本请求才是关键。正如我在评论中所发布的,该场景已经实现,它将
global
选项设置为
false
。这使得jQuery不会触发全局ajax事件。(但不知道为什么要实施这一计划。)

这可以通过(通过表示ajaxStop已启动)确认:

  • 跨域,无脚本:通过
  • 跨域,脚本:失败
  • 没有跨域,没有脚本:通过
  • 无跨域,脚本:通过
最直接的方法是添加另一个预过滤器,强制
global
选项为true:

jQuery.ajaxPrefilter( "script", function() {
    s.global = true;
});

这也使得这个失败的场景被忽略了。

不管怎么说,你都做错了:)

以下是可能发生的事情之一: 假设脚本被缓存,那么它们可能很快就会被加载。 因此,在第一次调用
$.getScript('js/script1.js')之后脚本将可用,并调用$.ajaxStop(may!!!),最坏的情况会发生三次

为了间接地回答你的问题,我会提出一个不同的解决方案,避免这种竞争条件。 您可以在这里尝试:


更新:稍微重构了代码

var urls, loadedUrls, log;

urls = [
    'https://raw.github.com/h5bp/html5-boilerplate/master/js/script.js',
    'https://raw.github.com/h5bp/html5-boilerplate/master/js/plugins.js',
    'https://raw.github.com/h5bp/html5-boilerplate/master/js/libs/modernizr-2.0.6.min.js'
];    

loadedUrls = [];

log = $( '#log' )[0];

urls.forEach(function ( url ) {
    $.getScript( url, function () {
        loadedUrls.push( url );

        $( log ).append( 'loaded ' + url + '<br>' );

        if( loadedUrls.length === urls.length ){
            $( log ).append( '<b>all done!</b>' );
        }
    });
});
var-url、loadedUrls、log;
URL=[
'https://raw.github.com/h5bp/html5-boilerplate/master/js/script.js',
'https://raw.github.com/h5bp/html5-boilerplate/master/js/plugins.js',
'https://raw.github.com/h5bp/html5-boilerplate/master/js/libs/modernizr-2.0.6.min.js'
];    
loadedUrls=[];
log=$('#log')[0];
forEach(函数(url){
$.getScript(url,函数(){
loadedUrls.push(url);
$(log).append('loaded'+url+'
'); if(loadedUrls.length==url.length){ $(log.append('all done!'); } }); });

现场演示:

在处理我自己的问题时,我找到了一个更好、更优雅的解决方案,它使用了。我想你已经知道这个函数了,也许是另一个用例,但是它对于加载文件和在所有事情完成后启动函数都非常有用。代码如下:

function getLatestNews() {
    return $.get('/echo/js/?delay=2&js=', function(data) {
        console.log('news data received');
        $('.news').css({'color':'blue'});
    });
}

function getLatestReactions() {
    return $.get('/echo/js/?delay=5&js=', function(data) {
        console.log('reactions data received');
        $('.reactions').css({'color':'green'});
    });
}

function prepareInterface() {
    return $.Deferred(function(dfd) {
        var latest = $('.news, .reactions');
        latest.slideDown(500, dfd.resolve);
        latest.addClass('active');
    }).promise();
}

$.when(
    getLatestNews(), 
    getLatestReactions(), 
    prepareInterface()
).then(function() {
    console.log('fire after requests succeed');
    $('.finished').html('I am done!');
}).fail(function() {
    console.log('something went wrong!');
});
我做了一把小小提琴,你可以在那里查看代码

您可以在那里查看一个正在运行的副本,我从本教程中获取了这个片段,值得阅读整个教程,其中有很多关于异步ajax的好信息


您是否尝试过将承诺与
$结合起来。when()
?(或者说,不管人们怎么做…@Pointy不,我还没有学会如何在jQuery中使用延迟。现在,我想知道为什么
.ajaxStop()
失败了——我一定是用错了什么东西了……我不知道;我从未尝试过使用它。我来看看能不能在你的提琴上实现诺言。(一件稍微奇怪的事情是,“ajaxStop”事件的触发方式与jQuery源代码中的其他事件不同。)它在1.2.6中工作。@john_doe:可能是因为带有跨域脚本的
ajaxPrefilter
(此处的场景)-请参阅。感谢您对此
:)
@kritzikratzi是的,拥有第二个阵列是一个很好的解决方案。你不需要
$.map
但是-在
URL
数组上调用
forEach
就足够了。@ŠimeVidas这是正确的,我写了很多mathematica代码,其中map和forEach基本相同…@kritzikratzi好吧,
每个
/
forEach
都是一般的迭代器机制,然而,
map
专门用于替换数组的值。是的,
$.when().then()
模式很酷
:)
我已经用这个模式解决了问题(请参阅我对上面问题的最后一条评论)。哦,我没有看到,它是隐藏的。啊,我喜欢这个模式!很好的解决方案。
var urls, loadedUrls, log;

urls = [
    'https://raw.github.com/h5bp/html5-boilerplate/master/js/script.js',
    'https://raw.github.com/h5bp/html5-boilerplate/master/js/plugins.js',
    'https://raw.github.com/h5bp/html5-boilerplate/master/js/libs/modernizr-2.0.6.min.js'
];    

loadedUrls = [];

log = $( '#log' )[0];

urls.forEach(function ( url ) {
    $.getScript( url, function () {
        loadedUrls.push( url );

        $( log ).append( 'loaded ' + url + '<br>' );

        if( loadedUrls.length === urls.length ){
            $( log ).append( '<b>all done!</b>' );
        }
    });
});
function getLatestNews() {
    return $.get('/echo/js/?delay=2&js=', function(data) {
        console.log('news data received');
        $('.news').css({'color':'blue'});
    });
}

function getLatestReactions() {
    return $.get('/echo/js/?delay=5&js=', function(data) {
        console.log('reactions data received');
        $('.reactions').css({'color':'green'});
    });
}

function prepareInterface() {
    return $.Deferred(function(dfd) {
        var latest = $('.news, .reactions');
        latest.slideDown(500, dfd.resolve);
        latest.addClass('active');
    }).promise();
}

$.when(
    getLatestNews(), 
    getLatestReactions(), 
    prepareInterface()
).then(function() {
    console.log('fire after requests succeed');
    $('.finished').html('I am done!');
}).fail(function() {
    console.log('something went wrong!');
});