【问题标题】:Why does my exit process execute before the loop ends?为什么我的退出过程在循环结束之前执行?
【发布时间】:2019-06-11 16:12:28
【问题描述】:

我来自 Ruby,所以我花了一天时间弄清楚为什么 process.exit(1) 在循环结束之前执行。有什么想法我需要更改才能使其正常工作吗?

export default async () => {
    const workbook = Xlsx.readFile(path.join(__dirname, './excel.xlsx'));
    const data = Xlsx.utils.sheet_to_json(workbook.Sheets.Extract, {
        header: getHeaderFor(workbook.Sheets.Extract),
    });
    await data.map(async (product, index) => {
        if (index < 6) return;
        await processProduct(product);
    });
    process.exit(1);
};

【问题讨论】:

  • 什么是processProduct? data 是什么?是数组吗?使用await Promise.all(data...) 而不是await data...
  • @estus 数据是一个数组。当我需要一个序列时,Promise.all 并行运行。
  • 然后就像答案所暗示的那样。不要使用map 进行迭代,它会产生一组promise,并且应该与Promise.all 一起使用。

标签: javascript node.js asynchronous sequelize.js


【解决方案1】:

我认为如果你替换:

await data.map(async (product, index) => {
    if (index < 6) return;
    await processProduct(product);
});

for (let i = 6; i < data.length; i++) {
  await processProduct(data[i]);
}

您的问题将得到解决。

一些解释: javascript 的 map 函数在为源数组的每个元素调用回调函数并将回调的返回值推入结果数组时,是从源数组创建新数组。在这种情况下await data.map(... 是无效语句,因为map 的结果是数组。要解决此问题,可以将结果包装在await Promise.all(data.map(...)) 中或使用普通的for 循环。当您不关心并发时可以使用第一种情况,而当您想要实现顺序时可以使用第二种情况。

【讨论】:

  • 它可以工作,但 ESlint 说 ESLint: Unexpected 'await' inside a loop.
  • @Meliborn 然后禁用比 ESLint 规则?当您知道它使您的异步任务串行运行时,循环中的等待还不错。它被 ESLint 标记是因为它可能会在应该使用 Promise.all 时意外使用。
【解决方案2】:

虽然@codtex 的回答会起作用,但它也会导致性能下降,因为循环的每次迭代都会等到上一次迭代。你真正想做的是收集所有的 Promise,然后等待它们完成:

const promises = data.map((product, index) => {
  if (index < 6) return;
  return processProduct(product);
});

await Promise.all(promises);

【讨论】:

  • 我知道,但我需要一个一个顺序运行,以防止条件竞争。
猜你喜欢
  • 1970-01-01
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 2014-01-25
相关资源
最近更新 更多