异步等待forEach

时间:2016-09-03 21:16:43

标签: javascript node.js ecmascript-2017

我有以下功能按预期工作:

  createObjectFrom(record) {
    let obj = {};

    this.opts.transformers.forEach((transformer, index) => {
      const headerIndex = findIndex(this.headers, (header) => {
        return header === transformer.column;
      });

      const value = transformer.formatter(record[headerIndex]);

      obj[transformer.field] = value;
    });

    return obj;
  }

我想重构它以使用async await并在forEach的主体中调用异步函数,如下所示:

  createObjectFrom(record) {
    let obj = {};

    this.opts.transformers.forEach(async (transformer, index) => {
      const headerIndex = findIndex(this.headers, (header) => {
        return header === transformer.column;
      });

      const result = await this.knex('managers').select('name')

      console.log(result);

      const value = transformer.formatter(record[headerIndex]);

      obj[transformer.field] = value;
    });

    return obj;
  }

这显然会破坏函数,因为forEach现在异步执行,函数只会执行并离开。

有没有办法可以使用异步等待forEach以同步方式执行。我可以重构发电机吗?

1 个答案:

答案 0 :(得分:1)

您无法强制执行正常的JS函数来等待异步行为。没有办法!

所以你必须重构你的createObjectFrom也是异步的。然后可能去map / reduce而不是forEach。 为了保持高效,你不想这样做:

for(transformer of this.opts.transformers) {
    await this.knex('managers').select('name');
}

相反,您应该使用await Promise.all(...)

但是在你的情况下,对knex的调用似乎不依赖于变压器,所以你可以这样做:

async createObjectFrom(record) {
  let obj = {};

  const result = await this.knex('managers').select('name')

  this.opts.transformers.forEach(async (transformer, index) => {
    const headerIndex = findIndex(this.headers, (header) => {
      return header === transformer.column;
    });

    console.log(result);

    const value = transformer.formatter(record[headerIndex]);

    obj[transformer.field] = value;
  });

  return obj;
}

但是如果你想为每个项目执行某些操作,那就像async一样:

async foo(data) {
  const subDataArr = await Promise.all(data.map(record => loadSubData(record)));

  return subDataArr;
}