【问题标题】:synchronizing deferreds with when将延迟与何时同步
【发布时间】:2012-09-12 16:21:38
【问题描述】:

我无法将已完成的 Deferred 与 $.when() 同步。 我希望在所有延期完成时收到通知,无论是解决还是失败。

我的问题是 when().always() 最初触发失败并且不等待其他延迟完成。不知道是不是bug。

我做了一个例子,这是一个 JsFiddle: http://jsfiddle.net/m3REv/

其中的js代码:

/* our multiple deferred we'd like to sync. */
var def1 = $.Deferred();
var def2 = $.Deferred();
var def3 = $.Deferred();

def1.done( function() { logger.log('1 done');} ).fail( function() {logger.log('1 fail');} );
def2.done( function() { logger.log('2 done');} ).fail( function() {logger.log('2 fail');} );
def3.done( function() { logger.log('3 done');} ).fail( function() {logger.log('3 fail');} );

$.when( def1, def2, def3 ).then( function() {
    logger.log('w then');
} ).done( function() {
    logger.log('w done');
} ).fail( function() {
    logger.log('w fail');
} ).always( function() {
    logger.log('w always');
});


def1.reject();
def2.resolve();
def3.resolve();

输出是:

1 fail
w fail
w always
2 done
3 done

【问题讨论】:

  • 这不是错误。 The docs 声明 when() 在第一个观察到的承诺失败时失败。 when() 返回的承诺失败解决它,所以它的always() 触发。不知道如何解决这个问题,您可能需要实现自己的 when-like 构造。
  • 好吧,那就是缺乏。我终于找到了一张相关的票:bugs.jquery.com/ticket/9386,但他们不会实现某些东西,直到有人先想出一个插件。 叹息

标签: jquery jquery-deferred


【解决方案1】:

解决方法:

var defCount = 3, state = 0;
var overallAlways = function () {
    if (++state < defCount) return;
    logger.log('correct always');
};

def1.done( function() { logger.log('1 done');} )
    .fail( function() {logger.log('1 fail');} )
    .always(overallAlways);
def2.done( function() { logger.log('2 done');} )
    .fail( function() {logger.log('2 fail');} )
    .always(overallAlways);
def3.done( function() { logger.log('3 done');} )
    .fail( function() {logger.log('3 fail');} )
    .always(overallAlways);

Source

或者类似的想法

function overallAlways(defObjects, callback) {
    var defCount = defObjects.length, state = 0;
    var alwaysCallback = function () {
        if (++state < defCount) return;
        callback.call(this);
    }
    $.each(defObjects, function (i, def) {
        def.always(alwaysCallback);
    });
}

var defs = [def1, def2, def3];
overallAlways(defs, function(){
    logger.log("overall always");
});

Source

【讨论】:

  • 嗯,这是一个可行的解决方法,但我希望我不必在每个延迟时绑定总是回调。
  • 你不必,你可以在done()fail()处理程序中调用overallAlways,但这违反了DRY原则。
  • 感谢您的帮助。无论如何,我已经重写了 $.when (请参阅我自己的答案)。现在我可以安然入睡了。
【解决方案2】:

最后我写了一个插件,它是 jQuery.when() 的略微修改版本。我没有对它进行详尽的测试,但它现在适用于小提琴和我的个人使用。

这是插件加上示例的小提琴:

http://jsfiddle.net/LTsLJ/

【讨论】:

    猜你喜欢
    • 2012-08-10
    • 1970-01-01
    • 2021-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    • 1970-01-01
    • 2019-05-16
    相关资源
    最近更新 更多