如何使用jQuery承诺链接三个asynchronous调用?

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

function first() { ajax() } function second() { ajax() } function third() { ajax() } function main() { first().then(second).then(third) } 

我试图使用延迟的两个function,我想出了一个部分的解决scheme。 我可以扩展它为三个function?

 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)}) 

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

这些对象是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); } 

参数datatextStatusjqXHR来自前一个函数$.ajax()调用。 first()提供second()second()提要third()

DEMO (用$.when('foo')来履行兑现的承诺,取代$.ajax(...) )。

当使用jQuery的promise时,实际上有一个更简单的方法。 看看下面的内容:

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

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

这是一个演练,如果你喜欢: http : //collaboradev.com/2014/01/27/understanding-javascript-promises-in-jquery/

这比这简单得多。

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

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

安静迟到回复,但我想答案是缺less一些直接代码链接。 既然你想要链接事件,可以很容易地做到,特别是与jQuery的承诺支持。 我使用下面的方法进行链接

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

它只是简单的没有复杂的循环或多个嵌套的callback。

你可以用更多的function来编写它:

 [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) 

我在这里find了一个好看的解决scheme: 如何链接jQuery 1.8.x中的一系列延迟函数?

这是我自己实施类似的方法,有点丑,但可能工作。 它将每个方法的结果作为“进度更新”广播到返回的承诺对象上。

  $.chain = function() { var def = $.Deferred(); var funcs = arguments; var left = arguments.length; function next() { if(left == 0) { def.resolve(); return; } var func = funcs[funcs.length - left]; // current func var prom = func(ret).promise(); // for promise will return itself, // for jquery ojbect will return promise. // these handlers will be launched in order we specify them prom.always(function() { left--; }).done(function(ret) { def.notify({ idx: funcs.length-left, left: left, result: ret, success: true, }); }).fail(function(ret) { def.notify({ idx: funcs.length-left, left: left, result: ret, success: false, }); }).always(function(ret) { next(ret); }); } next(); return def.promise(); }; 

如何使用它的情况? 也许不漂亮,但它应该工作:

 function first() { return ajax(...); } var id; funciton second() { return ajax(id, ...); } function third() { return ajax(id, ...); } $.chain(first, second, third).progress(function(p) { if(p.func == first) id = p.result.identifier; }).then(function() { alert('everything is done'); }); 

或者你可以从first函数中分配这个idvariables。

或者如果你只需要以前的函数的结果,你可以使用这种方法:

 function first() { return ajax(...); } function second(first_ret) { return ajax(first_ret.id, ...); } function third(second_ret) { return ajax(second_ret.something, ...); } 

以下似乎工作,并允许function列表是dynamic的:

 <html> <head> <title>demo chained synchronous calls</title> </head> <body> <script src="jquery-2.2.4.min.js"></script> <script type="text/javascript"> function one(parms) { console.log('func one ' + parms); return 1; } function two(parms) { console.log('func two ' + parms); return 2; } function three(parms) { console.log('func three ' + parms); return 3; } function four(parms) { console.log('func four ' + parms); return 4; } var funcs = ['one', 'two', 'three', 'four']; var rvals = [0]; function call_next_func() { if (funcs.length == 0) { console.log('done'); } else { var funcname = funcs.shift(); console.log(funcname); rvals.push(window[funcname](rvals)); call_next_func(); } } $(document).ready(function($){ call_next_func(); }); </script> </body> </html> 

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

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

这个函数接受一个返回promise对象的数组,比如你的三个函数。

用法示例:

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

这样first的结果也会自动成为second的参数,所以基本上是这样的:

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

当然,您可以根据需要添加尽可能多的函数。

我只是有同样的问题,链接ajax调用。 经过几天的努力,我终于做了$.ajax({ async: false,...完全做了我想要做的事,我只是没有想到,可能会帮助其他人…