【问题标题】:jQuery ajax deferred callback ordersjQuery ajax 延迟回调命令
【发布时间】:2013-05-27 20:40:15
【问题描述】:

我无法在延迟对象的回调之前执行每个 ajax 请求的 done/fail/always 回调。

我遇到的问题是我的一些 ajax 请求可能会失败,但我需要执行相同的代码,无论一个是否失败。

很难准确解释,所以我制作了这个小提琴来帮助说明我遇到的问题。 http://jsfiddle.net/zZsxV/

var a1 = $.Deferred();
var a2 = $.Deferred();
var a3 = $.Deferred();

a1.done(function() {
    $('body').append('a1 done<br />');     
}).fail(function() {
    $('body').append('a1 fail<br />');     
}).always(function() {
    $('body').append('a1 always<br />');     
});

a2.done(function() {
    $('body').append('a2 done<br />');     
}).fail(function() {
    $('body').append('a2 fail<br />');     
}).always(function() {
    $('body').append('a2 always<br />');     
});

a3.done(function() {
    $('body').append('a3 done<br />');     
}).fail(function() {
    $('body').append('a3 fail<br />');     
}).always(function() {
    $('body').append('a3 always<br />');     
});

var def = $.when(a1, a2, a3);
def.always(function() {
    $('body').append('defer always <-- should be after all<br />'); 
});

setTimeout(function() {
    a1.resolve();
}, 5000);
setTimeout(function() {
    a2.reject();
}, 1000);
setTimeout(function() {
    a3.resolve();
}, 3000);

我阅读了很多关于这个主题的答案,但我认为没有一个完全符合我的需要。

任何需要帮助的信息,请告诉我,我会在回来后添加。提前致谢。


编辑

我明白发生了什么。我只知道如何避免这个问题。我也尝试使用 .then 并获得相同的结果。一旦一个请求被拒绝,它会在等待其他回调之前触发失败回调。

【问题讨论】:

标签: jquery ajax


【解决方案1】:

根据jQuery documentation $.when所有参数被解析或一个被拒绝时触发回调。那么如何使用类似的东西而不是$.when

var custom_when = function() {
    var args = $.makeArray(arguments);
    var callback = args.pop();
    var all = [];
    $.each(args, function(index, def) {
        def.always(function() {
            var idx = all.indexOf(def);
            if (idx !== -1) {
                all.splice(idx, 1);
            }
            if (!all.length) {
                callback();
            }
        });
        all.push(def);
    });
};

你可以这样使用它:

custom_when(a1, a2, a3, function() {
    // do some stuff.
});

jsFiddle demo

【讨论】:

  • 这看起来不错。也感谢小提琴演示。直到今晚或明天,我才能将它实施到我的构建中。但是一旦我这样做了,我会回来报告的。
【解决方案2】:

我明白你在这里想要做什么,但没有方便的方法。这有效:

JSFIDDLE

$.when(a1).done(a2).done(a3).then(function() {
    $('body').append('defer always <-- should be after all<br />'); 
});

其他选项是编写您自己的简单函数。查看更新后的FIDDLE

whenAllResolved(a1, a2, a3).done(function () {
    $('body').append('defer always <-- should be after all<br />');
});


function whenAllResolved(){
    var d = $.Deferred(),
        args = arguments,
        verifyDeferreds = function(){
            var allResolved = true;
            $.each(args, function(i, arg){
                if(arg.state() === 'pending'){
                    allResolved = false;
                    return false;
                }
            });
            if (allResolved){
                d.resolve();
            }
        };

    $.each(arguments, function(i, arg){
        arg.always(verifyDeferreds);
    });

    verifyDeferreds();

    return d;
}

【讨论】:

  • 感谢您的功能和小提琴。我很快就会对其进行测试并报告。
【解决方案3】:

嘿,我遇到了类似的问题,我没有代码,但我会尝试找到它。

无论如何,我所做的是有一个变量,其中包含我需要等待的对象数量,并在其中一个完成时减少它,然后检查它是否为 0,如果它是我可以调用另一个函数。

【讨论】:

  • 我其实也有同样的想法。我真的很想避免它,我想只是为了更简洁的代码目的。感谢您的反馈意见。我很高兴看到您的解决方案,以防万一其他人不知道如果没有解决方法这是否可行。
  • 是我在需要时找到的唯一方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-15
  • 2012-07-09
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多