jQuery 延迟对象:使用多个对象的 $.when() 方法

8
我需要一种用回调函数获取不同脚本的方法。 这个方法可以正常运行:
fetchScripts:function() {
    var _this=this;
    $.when(
        $.ajax({
            url:_this.url + 'library/script-one.js',
            type:'get',
            cache:true
        }),
        $.ajax({
            url:_this.url + 'library/script-two.js',
            type:'get',
            cache:true
        }),
        { .... },
        $.ajax({
            url:_this.url + 'library/script-n.js',
            type:'get',
            cache:true
        })
    ).then(function() {
        console.log('fetch is done');

    })
},

但我希望更加通用的方法,因为冗余越来越多。 能否将promise传递给$.when()? 以下是我的第一次尝试-但url始终相同,即'script-n.js' 也许我错过了关键点,您可以提供一个更"优美"的解决方案

fetchScripts:function() {
    this.deferred=new $.Deferred();
    this.promise=this.deferred.promise();
    var _this=this;
    $.each([
        'script-one.js',
        'script-two.js',
        ( .... ),
        'script-n.js'
    ],function() {
        _this.script=this;
        _this.promise.then(function(){
            return $.ajax({
                url:_this.url + 'library/' + _this.script,
                type:'get',
                cache:true
            })
        });
    });
    $.when(
        this.promise
    ).then(function() {
        console.log('fetch is done');

    });
    this.deferred.resolve();
},
2个回答

28
你仍然需要使用$.when。但是,你需要创建一个Deferreds(或promises)数组,然后将其apply到$.when:
fetchScripts:function() {
    var base = this.url;
    var defaults = {
        type:'get',
        cache:true
    };

    var libraries = [
        'library/script-one.js',
        'library/script-two.js',
        'library/script-n.js'
    ];

    var deferreds = $.map(libraries, function(current) {
        var ajaxOptions = $.extend({ url:  base + current }, defaults);
        return $.ajax(ajaxOptions);
    });

    $.when.apply($, deferreds).then(function() {
        console.log('All done');
    });
}

除了扩展默认设置之外,您还可以只使用$.ajax(defaults)


要访问延迟值的结果,您可以在传递给.then的匿名函数内部使用arguments魔术变量。 - Sverri M. Olsen
1
我注意到在使用then()方法时,如果任何一个请求失败,你将进入其函数,尽管并没有全部完成,而使用done(),只有当最后一个仍在运行的请求完成时才会执行,无论是否有请求失败。 - Luis Martin

4

尝试

fetchScripts: function() {
    var deferred = new $.Deferred();
    var _this=this;

    var promises = $.map([
        'script-one.js',
        'script-two.js',
        ( .... ),
        'script-n.js'
    ], function(item, idx) {
        return $.ajax({
            url:_this.url + 'library/' + item.script,
            type:'get',
            cache:true
        })
    });

    $.when.apply($, promises).then(function() {
        console.log('fetch is done');
        deferred.resolve()
    });
    return deferred.promise();
}

1
我认为你的意思是使用$.map而不是$.each。另外只需要使用item,而不是item.script :-) - gen_Eric
@RocketHazmat 是的,复制粘贴错误。 - Arun P Johny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接