jQuery在并发ajax请求/then/失败时:哪个请求失败

jQuery when/then/fail with concurrent ajax requests: Which request failed?

本文关键字:失败 请求 并发 jQuery then ajax      更新时间:2023-09-26

想象一个场景,我们想在'foo'和'bar'的并发请求成功完成后做一些事情,或者在其中一个或两个请求失败时报告错误:

$.when($.getJSON('foo'), $.getJSON('bar'))
  .then(function(foo, bar) {
    console.log( 'I fire if BOTH requests are successful!' );
  })
  .fail(function() {
    console.log( 'I fire if one or more requests failed.' );
  });

我如何确定是否1)对'foo'的请求失败,或2)对'bar'的请求失败,或3)如果两者都失败?

只需在$.getJSON返回的每个promise中添加一个fail调用:

function make_error_handler(msg) {
    return function() { console.log(msg); };
}
$.when($.getJSON('foo').fail(make_error_handler("foo failed"))
            , $.getJSON('bar').fail(make_error_handler("bar failed")))
  .then(function(foo, bar) {
    console.log( 'I fire if BOTH requests are successful!' );
  })
  .fail(function() {
    console.log( 'I fire if one or more requests failed.' );
  });

如果您需要更细粒度的控制,您可以重载$.getJSON以向fail函数返回额外的信息——参见jQuery关于deferred.rejectWith的文档

jQuery.when

在多个deferred的情况下,其中一个deferred被拒绝,jQuery。当立即为它的主Deferred触发failcallback。请注意,在这一点上,一些延迟可能仍未解决。如果您需要为这种情况执行额外的处理,例如取消任何未完成的ajax请求,您可以在闭包中保留对底层jqXHR对象的引用,并在failCallback中检查/取消它们。

换句话说,您应该保留对每个请求的引用,如果需要的话,您应该自己手动检查。

困难在于当失败回调被调用时,任意数量的延迟仍然可以是未完成的,因此在那个状态下它们既没有失败也没有成功。

我希望文档能够更好地解释在这种情况下传递给失败处理程序的内容。从源代码来看,失败处理程序接收的参数似乎取决于哪个Deferred先失败:

args[ i ].promise().then( resolveFunc(i), deferred.reject );

我不是jQuery内部专家,但我认为这只是让你的每个Deferred调用"主"Deferred的reject方法与任何参数,它通常会传递给它的处理程序。不理想,如果你问我……但我可能会误读。

我想知道他们是否真的是这个意思:

args[ i ].promise().then( resolveFunc(i), func() { deferred.reject(args); } );

您可以调用.isResolved()来检查请求是否真正完成,但.when()的问题是,一旦请求失败,它就会失败,因此您无法可靠地判断另一个请求是否即将失败。

我相信我刚刚发布的类似问题的答案将解决(没有双关语的意思)这个需求,通过为每个AJAX查询创建一个额外的$.Deferred,这允许您等待,直到您知道两个AJAX调用的实际结果。