【问题标题】:Guaranteeing asynchronous request callback order in Javascript保证Javascript中的异步请求回调顺序
【发布时间】:2012-12-28 00:37:43
【问题描述】:

在 Javascript 中,我有两个异步数据请求:

$.getJSON('http://foo.com', fooQuery, fooSuccess(data));
$.getJSON('http://bar.com', barQuery, barSuccess(data));

还有两个回调来处理接收到的数据:

fooSuccess(data) { // Stuff }
barSuccess(data) { // More Stuff }

如何确保 barSuccess 仅在 fooSuccess 完成后执行?

注意事项:

  • 我想保持数据请求原样:异步和非阻塞(因为服务器响应可能需要一段时间)。
  • 但是,我希望处理数据的回调按顺序执行。也就是说,我不想在 fooSuccess 完成之前执行 barSuccess。

非常感谢您的智慧和帮助!

【问题讨论】:

标签: javascript jquery asynchronous callback


【解决方案1】:

以下是使用 ajax 请求返回的 jQuery 延迟对象的方法。

var fooDfd = $.getJSON('http://foo.com', fooQuery);
var barDfd = $.getJSON('http://bar.com', barQuery);

fooDfd.then(function(fooData){
    fooSuccess(fooData);
    barDfd.then(barSuccess);
});

【讨论】:

  • 虽然这会做 OP 想要做的事情,但最好使用 $.when().done() 构造来并行进行 AJAX 调用。
  • 这太完美了!如此简洁,完全符合我的要求。非常感谢大卫。
  • @MikeBrant 调用都是并行完成的,它们被前两行触发。
【解决方案2】:

最好的方法是像这样使用 jQuery when().done() 功能:

$.when(
    $.getJSON('http://foo.com', fooQuery, fooSuccess(data)), 
    $.getJSON('http://bar.com', barQuery, barSuccess(data))
).done(function(arg1, arg2){
    fooSuccess(arg1);
    barSuccess(arg2);
});

这允许同时执行 AJAX 请求并保证在所有请求成功完成后执行 done() 函数。

【讨论】:

  • 非常感谢迈克!我不知道使用 jQuery 有这么多不同的方法可以做到这一点。如果我不是这样的新手,我会同时支持你和大卫的回答(仍然低于支持的点阈值)。
  • 我们两个答案的区别在于,我允许 fooSuccess 处理程序仅在 http://foo.com 的响应下运行,而不是等待 bar 完成。
  • @david 确实。我想正确的方法是真正了解哪种方式产生最佳的整体响应时间。我想我假设 ajax 调用将是最耗时的,并且成功处理程序耗时更少,因此这意味着最好并行进行这些调用。如果必须尽早让fooSuccess 运行,那么在foo AJAX 调用所需时间少于bar AJAX 调用的所有情况下,您的方法都会更好。总而言之,OP 或许应该测试两种方式,看看哪种方式对它们有意义。
【解决方案3】:

我从半小时前开始关注这篇非常有趣的帖子,当出现@Mike Brant 提出的优雅解决方案时,我很快就潜入 jquery 库,看看它是如何产生的。不是吗?我推荐,很有趣! 顺便说一句,我认为我们不需要所有的魔法,在这种情况下,我们有两个异步调用处理程序(函数),无论哪个端首先,我们需要知道第二个结束的时间,那么我们只需要第三个函数这将由两个处理程序调用并在所有数据准备好时执行。我知道这种方法会比优雅的 jquery 解决方案多写四五行代码,但最终我们的大脑和灵魂会处于更好的状态。对不起我的英语。

【讨论】:

    【解决方案4】:

    barSuccess 调用放入fooSuccess 成功回调中。

    fooSuccess(data){
      jQuery.ajax({
        data: data,
        success: function(response){
          barSuccess(data) //should still be in scope, I think?
        }
      }
    }
    

    【讨论】:

    • 这将不允许barSuccess访问barQuery的返回值。
    • 更新后:这会链接 AJAX 调用,这是 OP 特别不想要的。所需要的就是实现这种效果的承诺或手动代码。
    • 感谢Colleen的回答,但这不是说bar的请求只有在foo的请求完成后才会发生?如果是这样,这不是我想要的。例如。如果 foo 请求和 bar 请求都需要 5 秒才能返回,我希望 fooSuccess 和 barSuccess 在 ~5 秒内完成处理,而不是 ~10 秒。
    • 啊,误解了——我认为一定程度的顺序是可以的,只要各个请求本身是异步的。
    • @ChrisHan,您正在寻找 jQuery 的 Deferred 实用程序。这确实是完全您所描述的。
    猜你喜欢
    • 1970-01-01
    • 2016-10-30
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 2015-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多