javascript javascript中的顺序函数调用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23451163/
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
Sequential function calls in javascript
提问by Priyanka A
I want function A to finish execution and only after that function B should start executing. When I call function A and then function B, it seems both are executing simultaneously. And after function B completes, I want to call a third function update_dropdown().
我希望函数 A 完成执行,并且只有在函数 B 之后才应该开始执行。当我调用函数 A 然后调用函数 B 时,似乎两者都在同时执行。在函数 B 完成后,我想调用第三个函数 update_dropdown()。
My code looks like this:
我的代码如下所示:
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();
});
}
Please can you tell me how I can make these 3 function calls happen sequentially.
请你告诉我如何让这 3 个函数调用顺序发生。
采纳答案by jfriend00
OK, it's getting a little bit clearer what you actually want (based on your recent comments to address clarifying questions) though there are still at least two options open.
好的,尽管仍有至少两个选项可供选择,但您真正想要的东西已经变得更清楚了(根据您最近提出的解决澄清问题的评论)。
For an operation like this, you probably want to take advantage of a number of promise features:
对于这样的操作,您可能希望利用许多承诺功能:
- jQuery's Ajax calls already return a promise so you can just use those directly
- To serialize operations, you can just chain multiple promise operations together
- To make async operations serialize properly, you can return a promise from a
.then()
handler and the master promise will resolve only when all the chained promises have resolved (kind of a built-in$.when()
without having to explicitly call$.when()
). - You can chain as many operations together as you want and the master promise will tell you when they are all done.
- If you return promises from both
A()
andB()
, then the callers of those functions can monitor when they are done with promise methods which then lets you chainA().then(B)
to sequence those two. - When you sequence operations with chaining, the prior methods resolve data is passed to the next
.then()
handler function in the chain as the first argument to the.then()
handler function so if you need the prior data for the next operation, it is right there to use.
- jQuery 的 Ajax 调用已经返回了一个 promise,所以你可以直接使用它们
- 要序列化操作,您可以将多个承诺操作链接在一起
- 为了使异步操作正确序列化,您可以从
.then()
处理程序返回一个承诺,并且只有当所有链接的承诺都已解决时,主承诺才会解决(一种内置的,$.when()
无需显式调用$.when()
)。 - 您可以根据需要将任意数量的操作链接在一起,主承诺会在它们全部完成时告诉您。
- 如果您同时从
A()
and返回 promiseB()
,那么这些函数的调用者可以监控它们何时使用 promise 方法完成,然后让您A().then(B)
将这两个方法链接起来。 - 当您使用链接对操作进行排序时,先前的方法解析数据将作为
.then()
处理函数的第一个参数传递给链中的下一个.then()
处理函数,因此如果您需要下一个操作的先前数据,它就可以使用。
So, with all those capabilities, it's just a matter of putting the right scaffolding around the code to implement the exact sequencing you want. Here are two different options:
因此,有了所有这些功能,只需在代码周围放置正确的脚手架即可实现您想要的精确排序。这里有两个不同的选项:
Option 1:If you want to serialize everything in A()
so that all 10 requests happen in serial fashion (the next one proceeds only when the prior one is done), then it could look like this:
选项 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);
Option 2:If you want the 5 pairs of requests in A()
to run in parallel, with only the last part of A()
waiting until the 5 pairs of requests are done, then it could look like this:
选项 2:如果您希望 5 对请求A()
并行运行,只有最后一部分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);
These use the concept that if you return a promise from a .then()
handler function, then it will chain multiple async operations together and the master promise is only resolved when all the chained operations are resolved. This is very powerful for sequencing multiple ajax operations and you can even do it for operations in a loop like you have.
这些使用的概念是,如果您从.then()
处理程序函数返回一个承诺,那么它会将多个异步操作链接在一起,并且主承诺仅在所有链接的操作都解决后才会解决。这对于对多个 ajax 操作进行排序非常强大,您甚至可以像您一样在循环中进行操作。
回答by adeneo
Something like this should work
这样的事情应该工作
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);
});
}
Note the use of an array to keep the promises in, then using $.when
with apply()
to fire a callback when all the ajax requests in the loop has finished.
请注意使用数组来保存承诺,然后在循环中的所有 ajax 请求完成时使用$.when
withapply()
触发回调。
回答by Roamer-1888
Assumptions assumptions ...
假设假设...
Let's assume that :
让我们假设:
- the url for every
get
is the same as that for its correspondingpost
- the urls for each get-post pair should vary
- the five get-post pairs in A can occur in parallel and we are not interested in the returned data
- 每个的 url
get
与其对应的 url相同post
- 每个 get-post 对的 url 应该有所不同
- A 中的五个 get-post 对可以并行发生,我们对返回的数据不感兴趣
First, a utility function :
首先,一个效用函数:
function getThenPost(url, appendToURL) {
return $.get(url).then(function(x) {
return (appendToURL) ? $.post(url + x) : $.post(url);
});
}
then A and B, both of which call the utility :
然后是 A 和 B,它们都调用了实用程序:
function A(urls) {
return $.when.apply(null, urls.map(function(url) {
return getThenPost(url, false);
}));
}
function B(url) {
return getThenPost(url, true);
}
and finally an expression that calls A and B :
最后是一个调用 A 和 B 的表达式:
A(['/path/0', '/path/1', '/path/2', '/path/3', '/path/4']).then(function() {
B('/path/5');
}).then(update_dropdown);
It should be reasonably simple to adjust this code if assumptions 1 and 2 are incorrect.
如果假设 1 和 2 不正确,调整此代码应该相当简单。
If assumption 3 is incorrect then A will require more extensive modification.
如果假设 3 不正确,则 A 将需要更广泛的修改。
回答by Ghanshyam
We can call our choice function in our way using jquery Deferred Object.
我们可以使用 jquery Deferred Object 以我们的方式调用我们的选择函数。
It is very simple let see successfully run example:
很简单,让我们看看成功运行的例子:
<body>
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">
// I want to call function in order of f1,f2,f3,f4 every time when i will execute this html page.
promise = f1().then(f2).then(f3).then(f4); // Add handlers to be called when the Deferred object is resolved, rejected, or still in progress.
function f1() {
var d = $.Deferred();
setTimeout(function() {
// our code here....
alert("1");
console.log("1");
d.resolve(); // resolve() :Resolve a Deferred object and call any doneCallbacks with the given args.
},1000); // You set some time for each method.
return d.promise(); //promise(): Return a Deferred's Promise object.
}
function f2() {
var d = $.Deferred();
setTimeout(function() {
alert("2");
console.log("2");
d.resolve();
},1000);
return d.promise();
}
function f4() {
var d = $.Deferred();
setTimeout(function() {
alert("4");
console.log("4");
d.resolve();
},1000);
return d.promise();
}
function f3() {
var d = $.Deferred();
setTimeout(function() {
alert("3");
console.log("3");
d.resolve();
},1000);
return d.promise();
}
</script>
回答by Bellian
Javascript without extra work is single threaded. that means functions are not able to be executed simultaneously. but the problem is that the $.get() and $.post() calls are asynchronous. that means they are executed whenever the requested data arrives your client. (first come first serve)
没有额外工作的 Javascript 是单线程的。这意味着不能同时执行功能。但问题是 $.get() 和 $.post() 调用是异步的。这意味着只要请求的数据到达您的客户端,它们就会被执行。(先到先得)
an solution would be to execute function B after all the results ob A arrived, or to hold back all results and handle all data at once then run update_dropdown()
.
一种解决方案是在所有结果 ob A 到达后执行函数 B,或者保留所有结果并立即处理所有数据然后运行update_dropdown()
。