Thats how I do it:
function processArray(array, index, callback) { processItem(array[index], function(){ if(++index === array.length) { callback(); return; } processArray(array, index, callback); }); }; function processItem(item, callback) { // do some ajax (browser) or request (node) stuff here // when done callback(); } var arr = ["url1", "url2", "url3"]; processArray(arr, 0, function(){ console.log("done"); });
Is it any good? How to avoid those spaghetti'ish code?
An object is an async iterator if it has a next() method. Every time you call it, it returns a promise that resolves to an object with the keys done (boolean) and value . Note how this is quite similar to the synchronous version of the iterator protocol.
The for loop runs immediately to completion while all your asynchronous operations are started. When they complete some time in the future and call their callbacks, the value of your loop index variable i will be at its last value for all the callbacks.
You need to place the loop in an async function, then you can use await and the loop stops the iteration until the promise we're awaiting resolves. You could also use while or do.. while or for loops too with this same structure. But you can't await with Array.
To iterate through an array of objects in JavaScript, you can use the forEach() method along with the for...in loop. The outer forEach() loop is used to iterate through the objects array. We then use the for...in loop to iterate through the properties of an individual object.
Checkout the async library, it's made for control flow (async stuff) and it has a lot of methods for array stuff: each, filter, map. Check the documentation on github. Here's what you probably need:
each(arr, iterator, callback)
Applies an iterator function to each item in an array, in parallel. The iterator is called with an item from the list and a callback for when it has finished. If the iterator passes an error to this callback, the main callback for the each
function is immediately called with the error.
eachSeries(arr, iterator, callback)
The same as each
only the iterator is applied to each item in the array in series. The next iterator is only called once the current one has completed processing. This means the iterator functions will complete in order.
As pointed in some answer one can use "async" library. But sometimes you just don't want to introduce new dependency in your code. And below is another way how you can loop and wait for completion of some asynchronous functions.
var items = ["one", "two", "three"]; // This is your async function, which may perform call to your database or // whatever... function someAsyncFunc(arg, cb) { setTimeout(function () { cb(arg.toUpperCase()); }, 3000); } // cb will be called when each item from arr has been processed and all // results are available. function eachAsync(arr, func, cb) { var doneCounter = 0, results = []; arr.forEach(function (item) { func(item, function (res) { doneCounter += 1; results.push(res); if (doneCounter === arr.length) { cb(results); } }); }); } eachAsync(items, someAsyncFunc, console.log);
Now, running node iterasync.js
will wait for about three seconds and then print [ 'ONE', 'TWO', 'THREE' ]
. This is a simple example, but it can be extended to handle many situations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With