10

想象一个场景,我们想要在 '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) 如果两者都失败了?

4

3 回答 3

11

只需为从返回的每个承诺添加一个失败调用$.getJSON

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以将其他信息返回给失败函数 - 请参阅 jQuery 的文档deferred.rejectWith

于 2011-04-26T19:01:26.900 回答
1

来自jQuery.when 的文档

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

换句话说,您应该保留对每个请求的引用,并在需要时自行手动检查。

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

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

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

我不是 jQuery 内部的专家,但我认为这只是让您的每个 Deferred 调用“主” Deferred 的reject方法,并使用通常传递给其处理程序的任何参数。不理想,如果你问我......但我可能误读了这个。

我确实想知道他们是否是这个意思:

args[ i ].promise().then( resolveFunc(i), func() { deferred.reject(args); } );
于 2011-09-14T11:39:35.710 回答
0

你可以打电话.isResolved()来检查一个请求是否真的完成了,但问题.when()是一旦任何一个请求失败,它就会失败,所以你不能可靠地判断另一个请求是否即将失败。

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

于 2011-04-28T21:34:51.007 回答