jQuery Deferred:具有多个对象的 $.when()

Posted

技术标签:

【中文标题】jQuery Deferred:具有多个对象的 $.when()【英文标题】:jQuery Deferred: $.when() with multiple objects 【发布时间】:2013-07-09 20:07:03 【问题描述】:

我需要一种通过回调获取不同脚本的方法。 这个方法没问题:

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');

    )
,

但我想更概括该方法,因为冗余正在增加。 是否可以向 $.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();
,

【问题讨论】:

【参考方案1】:

你仍然需要 $.when。但相反,创建一个 Deferreds(或 Promise)数组,然后 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 魔术变量; 我注意到在使用 then() 时,如果任何请求失败,尽管尚未完成,您仍将进入它的函数,而使用 done(),它只会在剩下的最后一个已经完成了,不管有没有失败。【参考方案2】:

试试

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();

【讨论】:

我想你的意思是$.map,而不是$.each。也只是item,而不是item.script :-) @RocketHazmat 是的,复制粘贴错误

以上是关于jQuery Deferred:具有多个对象的 $.when()的主要内容,如果未能解决你的问题,请参考以下文章

Deferred

Jquery 延迟对象

jQuery之Deferred对象P2

jQuery的Deferred对象

jquery中的 deferred之 deferred对象

jQuery中的deferred对象的使用