4

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?

5
  • First of all, it should be return await someAsyncFunctionOnObj(obj); But you really don't need async/await if you use Promise.all. Or just await Promise.all(arrayOfObjects.map(someAsyncFunctionOnObj)); Commented Oct 18, 2017 at 11:12
  • @dfsq yeah i was just showing the basic concept. Commented Oct 18, 2017 at 11:14
  • Why do you use Promise.all at all when you rather want to chain them? Commented Oct 18, 2017 at 11:16
  • @Robert that was exactly my question, what is the best way to chain them. 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 Commented Oct 18, 2017 at 11:32

3 Answers 3

3

Solution

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.com/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 completed.

queueAsyncFns waterfall graph

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for that explanation, this better answers my question!
1

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());

2 Comments

Could you explain the second line?
It takes all the promises in var promises and waits for them, one after the other, by the use of array reduce (array reduce use m as memory of the previous promise so we can do .then on m and return the next promise o, o becoming the new value of m and so on)
0
(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);
})();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.