【问题标题】:Waiting for async function to complete inside map等待异步功能完成内部地图
【发布时间】:2018-03-30 05:46:59
【问题描述】:

考虑下面的简单代码代码:

await Promise.all(arrayOfObjects.map(async (obj) => {
    return await someAsyncFunctionOnObj(obj);
}));

我的问题是,arrayOfObjectssomeAsyncFunctionOnObj 在执行时占用了太多内存,因为循环不会等待执行完成,而是调用 someAsyncFunctionOnObj (obj),在每一个上,并等待 全部解决,不需要按顺序,这会导致 OOM 崩溃。 我试过使用递归异步函数,它确实解决了顺序问题,但仍然导致 OOM 崩溃。

我要实现的流程是同步循环,意思是

await someAsyncFunctionOnObj(obj1); // wait for it to finish
await someAsyncFunctionOnObj(obj2); // wait for it to finish
...

对如何正确实施有什么建议吗?

【问题讨论】:

  • 首先应该是return await someAsyncFunctionOnObj(obj); 但是如果你使用Promise.all,你真的不需要async/await。或者只是await Promise.all(arrayOfObjects.map(someAsyncFunctionOnObj));
  • @dfsq 是的,我只是在展示基本概念。
  • 当你想要链接 Promise.all 时,为什么还要使用它们?
  • @Robert 这正是我的问题,链接它们的最佳方式是什么。
  • 您可能想要来自here 的示例,只需将第一个代码示例中的 RSVP 替换为 Promise 即可。它也很好地解释了它

标签: javascript typescript asynchronous


【解决方案1】:

解决方案

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

示例

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

上述功能应该可以解决您的问题。以下是它的作用的简要概述:

queueAsyncFns 接受一个函数数组,该数组返回调用异步函数的结果。通过调用每个函数并将 Promise 返回到 reducer 的下一次调用来减少该数组。在每次迭代中,异步调用的值都会累积到一个名为 values 的数组中,该数组会在所有项都被迭代后返回。

在运行示例时,可以通过查看瀑布图直观地确定函数的准确行为。您可以看到每个网络调用都是在前一个调用完成后进行的。

【讨论】:

  • 感谢您的解释,这更好地回答了我的问题!
【解决方案2】:

如果你想等待 someAsyncFunctionOnObj(obj1) 完成,然后再做同样的事情,但使用下一个对象(obj2,obj3,...),我认为你必须链接你的承诺:

var promises = arrayOfObjects.map(obj => someAsyncFunctionOnObj(obj));
await promises.reduce((m, o) => m.then(() => o), Promise.resolve());

【讨论】:

  • 你能解释一下第二行吗?
  • 它获取 var Promise 中的所有 Promise 并通过使用数组 reduce 一个接一个地等待它们(array reduce 使用 m 作为前一个 Promise 的内存,所以我们可以做 .then on m 并返回下一个 promise o,o 成为 m 的新值,依此类推)
【解决方案3】:
(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);
})();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-28
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 2020-09-13
    • 2019-05-31
    • 1970-01-01
    相关资源
    最近更新 更多