问题
I am running a post call inside a forEach loop. How do I see to that, it does not go to the next element in the list till the process for the first one is complete?
This is my array: arr = ['Hermione', 'Ron', 'Harry']
Here is my loop:
arr.forEach(d=>{
$('#the_table>tbody').append(`
<tr id='tr_${d}'>
<td'>${d}</td>
<td><i id='change' class='no'></i></td>
</tr>
`);
});
const myfunc = () => {
$.post(api, json_object,
function(data, status) {
if (data.value === 'started') {
setTimeout(myfunc, 5000);
} else {
$('#change').removeClass('no').addClass('yes');
}
}, 'json');
}
myfunc();
I want to start with the first element Hermione
. Till the status changes from started
to done
, I don't want to start the process on the second element Ron
and so on.
How do I do that?
回答1:
You don't need a recursive function; you need to use the Promise api (async/await), with their buddies .then()
.when()
.next()
etc. The basic problem you are facing is that you need results returned in a certain order, and ajax is asynchronous (things happen when they happen, not necessarily in order) - but you need them in a certain order.
In the beginning was the XMLHttpRequest (XHR), and (for the first time!) it allowed client-side javascript to communicate with a backend server, and receive a response with new data that could be parsed and added to the DOM without leaving or refreshing the page. And it was tricky and difficult, and few there be'd who used it - but it worked.
.then()
along came John Resig and he invented jQuery and within it he included the $.ajax()
construct, along with its shortcut cousins $.get()
$.post()
and $.load()
- and XHR was significantly easier. And the world rejoiced! But because it was asynchronous, it was still kinda tricky to get the values out of the functions in the right order when you had several related ajax calls to make.
.then()
along came the Promise api - because what could be easier than having your code make a Promise and wait for it to be fulfilled? And the world rejoiced once again, and there was no looting. You just set up a promise and .then()
you can use .after()
and .next()
and .when()
and, of course, .then()
for truly readable code that was as easy to read as it was to write.
And nothing could possibly be easier! Until 2017, when async
and await
were added to ECMAScript. Now all you have to do is add the keyword async
at the top of a function scope, and then within it you can use the await
keyword to write those promises for you. Because async/await
is really just a wrapper for the Promises api, you can still use .then()
.when()
.next()
etc. - but your code is more readable and simpler to write!
And the world rejoiced, and still there was no looting.
WttW*: This (async/await and Promises api) is something you absolutely must get your head around - it will be more useful to you each day.
*Word to the Wise
References:
https://blog.bitsrc.io/understanding-javascript-async-and-await-with-examples-a010b03926ea
https://petetasker.com/using-async-await-jquerys-ajax/
来源:https://stackoverflow.com/questions/62182786/dont-process-next-element-in-foreach-loop-till-the-process-for-first-is-over