【问题标题】:Async calls in loop delayed循环中的异步调用延迟
【发布时间】:2019-11-04 11:12:40
【问题描述】:

我有一个函数,它在一个循环内对数据库进行两次异步调用。问题是返回函数在从循环中检索数据之前起作用。

const myFunc = async (customers) => {
  const customerList = customers.map(async (customer) => {
    const cashCollected = await knex('cash_collections')
      .sum('amount_collected as amount')
      .where('account_code', customer.code)
      .first();
    const orderValue = await knex('orders')
      .sum('discounted_price as amount')
      .where('customer_id', customer.id)
      .first();
    const customerData = {
      name: customer.name,
      outstandingBalance: (orderValue.amount - cashCollected.amount),
    };
    // This line works after console.log(customerList);
    console.log(customerData);
    return customerData;
  });
   // console and return works before data is retrieved 
   // (before console.log(customerData) is run)
  console.log(customerList);
  return customerList;
};

// Function is called in another place
myFunc()

【问题讨论】:

  • 因此,我们不会将部分答案折叠到问题中。我们将它们分开。编码愉快!

标签: javascript database async-await knex.js


【解决方案1】:

通过在map 回调中执行所有这些调用,您可以并行进行所有这些调用。如果您真的想这样做,则需要使用Promise.all 等待这些电话解决:

const customerList = await Promise.all(customers.map(async (customer) => {
    // ...
}));

如果您想连续执行它们,请使用for 循环并等待每个响应。 :-) 但看起来并行是可以的。

【讨论】:

    【解决方案2】:

    你需要 await 地图然后它会等待它,否则异步不会让它等待它实际上意味着它继续下一个代码,除非你告诉它await。像这样: const customerList = await customers.map.... 现在,由于 map 不返回承诺,您需要使用 Promise.all 或单独的承诺将其包装在承诺中。

    【讨论】:

    • map 不返回承诺。
    • 编辑仍然有await customers.map,恐怕它不会做任何有用的事情。您想等待 map 返回的数组中的承诺(例如,我在通过 Promise.all 的回答中这样做了)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-25
    • 1970-01-01
    • 1970-01-01
    • 2015-08-11
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多