简体   繁体   English

等待异步功能完成内部地图

[英]Waiting for async function to complete inside map

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. 我的问题是, arrayOfObjectssomeAsyncFunctionOnObj在执行时占用太多内存,因为循环不会等待执行完成,而是在每一个上调用someAsyncFunctionOnObj(obj),并等待直到所有内容都被解析 ,而不是必需的按顺序,这会导致OOM崩溃。 Iv'e tried using a recursive async function, which does solve the order problem, but still causes OOM crash. 我尝试使用递归异步函数,这确实解决了订单问题,但仍导致OOM崩溃。

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? 有关如何正确实施它的任何建议?

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. queueAsyncFns接受一组函数,这些函数返回调用异步函数的结果。 This array is reduced by calling each function and returning the Promise to the next call of the reducer. 通过调用每个函数并将Promise返回到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. 每次迭代时,异步调用的值都会累积到一个名为values的数组中,这些数组在迭代完所有项后返回。

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瀑布图

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: 如果你想在做同样的事情之前等待someAsyncFunctionOnObj(obj1)完成但是使用下一个对象(obj2,obj3,...),我认为你必须链接你的承诺:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM