如何使用jQuery promises链接三个异步调用?

Joh*_*ock 66 javascript jquery asynchronous deferred

我需要以同步方式进行三次HTTP调用,如何将数据从一个调用传递到另一个调用?

function first()
{
   ajax()
}

function second()
{
   ajax()
}

function third()
{
   ajax()
}


function main()
{
    first().then(second).then(third)
}
Run Code Online (Sandbox Code Playgroud)

我试图将延迟用于两个函数,我想出了一个部分解决方案.我可以将它扩展为三个功能吗?

function first() {
    var deferred = $.Deferred();
     $.ajax({

             "success": function (resp)
             {

                 deferred.resolve(resp);
             },

         });
    return deferred.promise();
}

function second(foo) {
     $.ajax({
            "success": function (resp)
            {
            },
            "error": function (resp)
            {
            }
        });
}


first().then(function(foo){second(foo)})
Run Code Online (Sandbox Code Playgroud)

Bee*_*oot 80

在每种情况下,返回由返回的jqXHR对象$.ajax().

这些对象是Promise兼容的,因此可以用.then()/ .done()/ .fail()/ 链接.always().

.then() 在这种情况下,你想要的就是问题中的那个.

function first() {
   return $.ajax(...);
}

function second(data, textStatus, jqXHR) {
   return $.ajax(...);
}

function third(data, textStatus, jqXHR) {
   return $.ajax(...);
}

function main() {
    first().then(second).then(third);
}
Run Code Online (Sandbox Code Playgroud)

参数data,textStatus并且jqXHR来自$.ajax()前一个函数中的调用,即.first()饲料second()second()饲料third().

DEMO(以$.when('foo')履行承诺,代替$.ajax(...)).

  • 这对我不起作用.当我尝试你的例子时,第一个结果传递给第二个和第三个.所以先喂第二和第三.不是先喂第二,第二喂第三.$ .ajax({...}).then(function(..){return $ .ajax({...});}).then(function(...){/*我想要的结果来自第二个电话.*/}); (7认同)
  • 刚用jquery 1.11.0进行检查,然后调用get来自何时而不是之前的参数. (2认同)

小智 35

在使用jQuery的promises时,实际上有一种更简单的方法.看看以下内容:

$.when(
    $.ajax("/first/call"),
    $.ajax("/second/call"),
    $.ajax("/third/call")
    )
    .done(function(first_call, second_call, third_call){
        //do something
    })
    .fail(function(){
        //handle errors
    });
Run Code Online (Sandbox Code Playgroud)

只需将所有调用链接到$ .when(...)调用并处理.done(...)调用中的返回值.

如果您愿意,可以参考以下内容:http: //collaboradev.com/2014/01/27/understanding-javascript-promises-in-jquery/

  • 不是OP正在寻找的答案,而是我所在的答案.谢谢! (14认同)
  • 这个例子中的三个ajax调用将异步**** (13认同)
  • @Emilio,是的.这就是OP所要求的,而这个答案在这方面没有提供. (8认同)
  • 回答一个完全不同的问题.建议删除以避免混淆. (8认同)
  • 这个答案不会链接请求,而是并行运行. (4认同)
  • 关于这个的一个问题.如果"/ first/call"在第二次调用"second/call/id"中返回我需要的ID怎么办?在这种情况下,我需要先获得第一个调用的结果,然后是第二个调用的结果. (3认同)
  • DV:未回答问题-误导 (2认同)

pra*_*tha 24

很晚回复,但我猜答案缺少一些直接的链接代码.链接事件非常简单,在jquery中有promise支持.我使用以下链接:

$.ajax()
.then(function(){
   return $.ajax() //second ajax call
})
.then(function(){
   return $.ajax() //third ajax call
})
.done(function(resp){
   //handle final response here
 })
Run Code Online (Sandbox Code Playgroud)

它很简单,没有复杂的for循环或多个嵌套的回调.


SLa*_*aks 14

它比那简单得多.

$.ajax 已经返回一个promise(Deferred对象),所以你可以简单地写

function first() {
    return $.ajax(...);
}
Run Code Online (Sandbox Code Playgroud)

  • @SLaks - 请扩展你的答案以更好地解释所提出的问题,因为看起来你的答案对于jQuery ajax对象的本质和基础是非常重要的,它应该有更多的线来解释如何链接多个异步函数 (4认同)
  • 如何链接多个ajax调用并传递返回值?deferred.resolve曾经是我以前的方式. (2认同)

小智 6

您可以通过更实用的方式编写它:

[function() { return ajax(...)}, function(data) { return ajax(...)}]
.reduce(function(chain, callback) { 
  if(chain) { 
    return chain.then(function(data) { return callback(data); });
  } else {
    return callback();
  }
}, null)
Run Code Online (Sandbox Code Playgroud)


Dun*_*Luk 5

最好的方法是为此创建一个可重用的函数。这甚至可以使用一行代码来完成reduce

function chainPromises(list) {
    return list.reduce((chain, func) => chain ? chain.then(func) : func(), null);
}
Run Code Online (Sandbox Code Playgroud)

这个函数接受一个回调数组,它返回一个 promise 对象,就像你的三个函数一样。

用法示例:

chainPromises([first, second, third]).then(function (result) {
    console.log('All done! ', result);
});
Run Code Online (Sandbox Code Playgroud)

这样, 的结果也first将自动成为 的参数second,所以基本上会发生这样的事情:

first().then(function(res1) { return second(res1) })
       .then(function(res2) { return third(res2)  })
       .then(function(result) { console.log('All done! ', result) });
Run Code Online (Sandbox Code Playgroud)

当然,您可以根据需要向数组添加任意数量的函数。