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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5794964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 18:22:07  来源:igfitidea点击:

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

javascriptjqueryjquery-deferred

提问by Javier

Imagine a scenario where we want to do something after the concurrent requests for 'foo' and 'bar' have completed successfully, or report an error if one or both of them fails:

想象一个场景,我们想要在 '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.' );
  });

How can I determine if 1) the request for 'foo' failed, or 2) the request for 'bar' failed, or 3) if both failed?

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

回答by Sean Vieira

Simply add a fail call to each promise that is returned from $.getJSON:

只需向从 返回的每个承诺添加一个失败调用$.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.' );
  });

If you need more fine-grained control you can overload $.getJSONto return additional information to the fail function -- see jQuery's documentation on deferred.rejectWith

如果您需要更细粒度的控制,您可以重载$.getJSON以将附加信息返回给失败函数——请参阅 jQuery 的文档deferred.rejectWith

回答by Roman Starkov

From the documentation on jQuery.when

来自jQuery.when 的文档

In the multiple-Deferreds case where one of the Deferreds is rejected, jQuery.when immediately fires the failCallbacks for its master Deferred. Note that some of the Deferreds may still be unresolved at that point. If you need to perform additional processing for this case, such as canceling any unfinished ajax requests, you can keep references to the underlying jqXHR objects in a closure and inspect/cancel them in the failCallback.

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

In other words, you are supposed to keep the references to each request, and check it manually yourself, if you need to.

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

The difficulty is that when the fail callback is called, any number of deferred's can still be outstanding, thus at that state they have neither failed nor succeeded.

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

I wish the documentation explained a bit better as to exactly what is passed to the fail handler in this case. Judging from the source code though, it seems that the arguments received by the fail handlers depend on which Deferred fails first:

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

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

I'm no expert on jQuery internals, but I think this simply lets each of your Deferred's call the "master" Deferred's rejectmethod with whatever arguments it would normally pass to its handlers. Not ideal, if you ask me... but then I could be misreading this.

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

I do wonder if they meant this though:

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

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

回答by Alnitak

You could call .isResolved()to check whether a request did actually complete, but the problem with .when()is that it'll fail as soon as eitherrequest fails, so you can't reliably tell whether the other request might be about to fail.

您可以调用.isResolved()以检查请求是否确实完成,但问题.when()是只要其中一个请求失败,它就会失败,因此您无法可靠地判断另一个请求是否可能会失败。

I believe the answer I just postedto a similar questionwill resolve (no pun intended) this requirement, by creating an extra $.Deferredfor each AJAX query, which allows you to wait until you know the actual outcome of both AJAX calls.

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