javascript中的顺序函数调用

我希望函数A完成执行,并且只有在函数B开始执行之后才能执行。 当我调用函数A然后调用函数B时,它们似乎都在同时执行。 在函数B完成后,我想调用第三个函数update_dropdown()。

我的代码如下所示:

function A { for (var i = 0; i < 5; i++) { var promise = $.get(url+i); $.when(promise).then(function () { $.post(url); }); } } function B { var x = $.get(url); var promise = $.post(url+x); $.when(promise0).then(function () { update_dropdown(); }); } 

请问您能告诉我如何按顺序进行这3个函数调用。

好吧,虽然仍然至少有两个选项可供选择,但是你真正想要的更清楚一些(基于你最近的评论来解决澄清问题)。

对于这样的操作,您可能希望利用许多承诺function:

  1. jQuery的Ajax调用已经返回一个promise,所以你可以直接使用它们
  2. 要序列化操作,您可以将多个承诺操作链接在一起
  3. 要使异步操作正确序列化,您可以从.then()处理程序返回一个promise,并且只有当所有链接的promise都已解析时,master promise才会解析(内置的$.when()而不必显式调用$.when() )。
  4. 您可以根据需要将多个操作链接在一起,主承诺会告诉您何时完成所有操作。
  5. 如果你从A()B()返回promises,那么这些函数的调用者可以监视完成promise方法的时间,然后让你链接A().then(B)对这两个进行排序。
  6. 当您使用链接对操作进行排序时,先前方法解析数据将作为.then()处理函数的第一个参数传递给链中的下一个.then()处理函数,因此如果您需要先前数据用于下一个操作,它就在那里使用。

因此,利用所有这些function,只需在代码周围放置正确的脚手架即可实现您想要的精确排序。 这有两个不同的选择:


选项1:如果要序列化A()中的所有内容,以便所有10个请求以串行方式发生(下一个请求仅在前一个请求完成时继续),那么它可能如下所示:

 // serialize all requests function A() { var p = $.get(url).then(function(data) {return $.post(url)}); for (var i = 1; i < 5; i++) { // chain four more pairs of requests onto the original promise p = p.then(function() {return $.get(url)}) .then(function(data) {return $.post(url)}); } // return the promise so callers can monitor when A() is done return p; } function B() { // sequence these three operations one after the other return ($.get(url) .then(function(data) {return $.post(url + x)}) .then(update_dropdown) ); } // run them both, one after the other A().then(B); 

选项2:如果您希望A()的5对请求并行运行,只有A()的最后一部分等待,直到5对请求完成,那么它可能如下所示:

 // parallelize pairs of requests function A() { var promises = []; for (var i = 0; i < 5; i++) { // execute 5 pairs of requests where each pair is serialized in itself promises.push($.get(url).then(function(data) {return $.post(url)})); } // return a promise that resolves only when all the other promises are done return $.when.apply($, promises); } function B() { // sequence these three operations one after the other return ($.get(url) .then(function(data) {return $.post(url + x)}) .then(update_dropdown) ); } // run them both, one after the other A().then(B); 

它们使用的概念是,如果从.then()处理函数返回一个promise,那么它会将多个异步操作链接在一起,并且只有在解析了所有链接操作后才能解析主promise。 这对于对多个ajax操作进行排序非常强大,您甚至可以像循环一样在循环中进行操作。

这样的事情应该有效

 function A { var xhr = []; for (var i = 0; i < 5; i++) { xhr.push( $.get(url) ); } $.when.apply($, xhr).then(B); } function B { $.get(url).done(function(x) { $.post(url + x).done(update_dropdown); }); } 

注意使用数组来保持promises,然后使用$.whenapply()在循环中的所有ajax请求完成时触发回调。

假设假设……

我们假设:

  • 每次get的url与其相应post的url相同
  • 每个发布对的url应该有所不同
  • A中的五个get-post对可以并行发生,我们对返回的数据不感兴趣

一,效用函数:

 function getThenPost(url, appendToURL) { return $.get(url).then(function(x) { return (appendToURL) ? $.post(url + x) : $.post(url); }); } 

然后A和B,两者都调用该实用程序:

 function A(urls) { return $.when.apply(null, urls.map(function(url) { return getThenPost(url, false); })); } function B(url) { return getThenPost(url, true); } 

最后是一个调用A和B的表达式:

 A(['/path/0', '/path/1', '/path/2', '/path/3', '/path/4']).then(function() { B('/path/5'); }).then(update_dropdown); 

如果假设1和2不正确,则调整此代码应该相当简单。

如果假设3不正确,那么A将需要更广泛的修改。

我们可以使用jquery Deferred Object以我们的方式调用我们的选择函数。

很简单就看看成功运行的例子:

    

没有额外工作的Javascript是单线程的。 这意味着function无法同时执行。 但问题是$ .get()和$ .post()调用是异步的。 这意味着只要请求的数据到达您的客户端,它们就会被执行。 (先到先得)

一个解决方案是在所有结果ob A到达后执行函数B,或者阻止所有结果并立即处理所有数据然后运行update_dropdown()