【问题标题】:async/await nested in cycle异步/等待嵌套在循环中
【发布时间】:2018-10-16 23:41:28
【问题描述】:

我有一个基本的快速路由器。对数据库进行异步调用以获取数据数组。然后,使用这个数组,我正在循环执行另一个异步调用。但我不知道如何让它按照我希望它工作的顺序工作。 代码:

const db = require('../models/index');
const router = require('express').Router();
const Op = db.Sequelize.Op;

router.get('/', async function (req, res) {
  const dataSet = await db.sequelize.models.model1.findAll({
    raw: true,
    include: [{
      model: db.sequelize.models.model2,
    }, {
      model: db.sequelize.models.model3,
      required: true
    }],
    limit: 10,
    order: ['flight_date']
  });

  dataSet.forEach(async (item) => {
    delete item.id;
    const mealQtyP = await db.sequelize.models.model4.findAll({
      raw: true,
      where: {
        sampleField: sampleFieldCondition,
      }
    });

    console.log('from cycle'); //but it logged after "shall log after all"
  });

  console.log('shall log after all'); //want it to be logged after all
});

module.exports = router;

【问题讨论】:

  • 您希望它的工作顺序是什么?
  • 使其记录“从循环”n次,然后记录“毕竟应该记录”
  • sampleFieldCondition 是否可以让您运行一次findAll 并通过一次调用获得所有结果,例如。使用or 运算符?这将有助于减少数据库的负载,更快地执行,并可能使代码更易于阅读。
  • 不,我必须为每个元素获取数据

标签: javascript node.js async-await


【解决方案1】:

如果您希望在处理完dataSet 中的每个项目之后打印“毕竟应该记录”,您可以将数据集项目映射到Promises,然后再映射到awaitPromise.all()

await Promise.all(dataSet.map(async (item) => {
    delete item.id;
    const mealQtyP = await db.sequelize.models.model4.findAll({
        raw: true,
        where: {
            sampleField: sampleFieldCondition,
        }
    });

    console.log('from cycle'); //but it logged after "shall log after all"
}));

console.log('shall log after all'); //want it to be logged after all

因为你将一个异步函数传递给map,它会返回一个Promise,所以map的结果是一个Promises的数组。 Promise.all() 返回一个Promise,当数组中的所有原始Promises 都被解析时,该Promise 被解析;因此,等待这个Promise 将等到dataSet 中的每个项目都已处理完毕。

修改此代码以实际为您提供结果:

const results = await Promise.all(dataSet.map(async (item) => {
    console.log('from cycle'); //but it logged after "shall log after all"
    delete item.id;
    return db.sequelize.models.model4.findAll({
        raw: true,
        where: {
            sampleField: sampleFieldCondition,
        }
    });
}));

console.log('shall log after all'); //want it to be logged after all
console.log('here are my results:', results);

【讨论】:

  • 我希望它在循环中进行所有异步调用,即遍历 dataSet 的元素,然后将这些调用的所有结果一起抓取,然后映射到某个数组,然后成为能够使用这个数组
  • 正确的方法,@laptou - 不过,请确保您确实从 map 调用中返回了 findAll Promise,例如, const mealQtyP = await Promise.all( dataSet.map(async (item) => { delete item.id; return db.sequelize.models.model4.findAll({ raw: true, where: { sampleField: sampleFieldCondition } }); }); ) // mealQtyP 是一个包含所有 findAll 结果的数组
  • @AndreiAleksandrov 喜欢这样吗?
  • @AndreasPizsa 已修复
  • 不,我需要将循环中每个异步调用的结果添加到每个项目中,这个循环正在迭代
猜你喜欢
  • 2020-04-12
  • 2018-07-13
  • 1970-01-01
  • 2018-06-25
  • 2020-10-17
  • 2018-06-04
  • 2012-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多