consider the following simple code code:
await Promise.all(arrayOfObjects.map(async (obj) => {
return await someAsyncFunctionOnObj(obj);
}));
My problem is, arrayOfObjects, and someAsyncFunctionOnObj, take too much memory while executing, because the loop doesn't wait for the execution to finish, instead it calls someAsyncFunctionOnObj(obj), on each one, and waits till all are resolved, not necessary in order, this causes OOM crash. Iv'e tried using a recursive async function, which does solve the order problem, but still causes OOM crash.
The flow I want to achieve is a synchronous loop, meaning
await someAsyncFunctionOnObj(obj1); // wait for it to finish
await someAsyncFunctionOnObj(obj2); // wait for it to finish
...
Any suggestions on how to correctly implement it?
consider the following simple code code:
await Promise.all(arrayOfObjects.map(async (obj) => {
return await someAsyncFunctionOnObj(obj);
}));
My problem is, arrayOfObjects, and someAsyncFunctionOnObj, take too much memory while executing, because the loop doesn't wait for the execution to finish, instead it calls someAsyncFunctionOnObj(obj), on each one, and waits till all are resolved, not necessary in order, this causes OOM crash. Iv'e tried using a recursive async function, which does solve the order problem, but still causes OOM crash.
The flow I want to achieve is a synchronous loop, meaning
await someAsyncFunctionOnObj(obj1); // wait for it to finish
await someAsyncFunctionOnObj(obj2); // wait for it to finish
...
Any suggestions on how to correctly implement it?
Share Improve this question edited Oct 18, 2017 at 11:14 vrachlin asked Oct 18, 2017 at 11:03 vrachlinvrachlin 8175 silver badges16 bronze badges 5-
First of all, it should be
return await someAsyncFunctionOnObj(obj);
But you really don't need async/await if you usePromise.all
. Or justawait Promise.all(arrayOfObjects.map(someAsyncFunctionOnObj));
– dfsq Commented Oct 18, 2017 at 11:12 - @dfsq yeah i was just showing the basic concept. – vrachlin Commented Oct 18, 2017 at 11:14
- Why do you use Promise.all at all when you rather want to chain them? – Rob Commented Oct 18, 2017 at 11:16
- @Robert that was exactly my question, what is the best way to chain them. – vrachlin Commented Oct 18, 2017 at 11:23
- You probably want the example from here, just replace RSVP with Promise in the first code example. It explains it pretty well too – tocallaghan Commented Oct 18, 2017 at 11:32
3 Answers
Reset to default 3Solution
async function queueAsyncFns(fns) {
const values = [];
await fns.reduce((previous, current, index, array) => {
const thenable = index === 1 ? previous() : previous;
return thenable.then(value => {
values.push(value);
return index === array.length - 1 ? current().then(value => values.push(value)) : current();
});
});
return values;
}
Example
const anArray = [1, 2, 3];
const doSomething = async (id) => await fetch(`https://jsonplaceholder.typicode./users/${id}`).then(res => res.json());
queueAsyncFns(anArray.map((val) => () => doSomething(val))).then((val) => console.log(val));
The above function should solve your issue. Here's a brief overview of what it does:
queueAsyncFns
accepts an array of functions that returns the result of calling an async function. This array is reduced by calling each function and returning the Promise to the next call of the reducer. With each iteration the value of the async call is accumulated into an array called values
which is returned after all items have been iterated through.
The accurate behaviour of the function can be determined visually by looking at the waterfall graph when running the example. You can see each network call is only made after the previous one has been pleted.
If you want to wait for someAsyncFunctionOnObj(obj1) to finish before doing the same but with the next object (obj2, obj3, ...), I think you have to chain your promises:
var promises = arrayOfObjects.map(obj => someAsyncFunctionOnObj(obj));
await promises.reduce((m, o) => m.then(() => o), Promise.resolve());
(async function() {
async function executeSequentially() {
const tasks = [1,2]
const total = []
for (const fn of tasks) {
const res = await fetch(endpoint);
const res2 = await res.json();
console.log(res2[0]);
total.push(...res2);
}
return total;
}
const res = await executeSequentially();
console.log(res);
})();