【问题标题】:Async function inside for loopfor循环内的异步函数
【发布时间】:2019-04-07 01:10:09
【问题描述】:

我正在构建一个应用程序,但我在 for 循环中遇到了问题。

在我的函数中,我得到了两个数组作为参数(payload.data.start 和 payload.data.end),我试图将它推入 mongodb。 我的代码是这样的

async function emplaceAval (state, payload, blockInfo, context) {
  for(var i=0 ; i<payload.data.start.length ; i++) // start and end have the same length
  {
    const user =await User.findOne({ 'account': payload.data.account })
    user.availability.push({start: new Date(payload.data.start[i]+'Z') , end: new Date(payload.data.end[i]+'Z')});
    await user.save();
  }
}

问题是我经常丢失数据。丢失数据是指 i 在 user.save 发生之前发生变化。

我考虑使用 forEach ,但是我有两个数组需要一起保存,所以我不能。

我认为的第二种解决方案是创建一个索引数组。例如,如果我的数组的长度是 5 ,我将创建一个 indexTable=[0 , 1 , 2 , 3 , 4 ] 并且我将使用 asyncForEach 这个数组。但我不认为这种解决方案是可取的。 有任何想法吗?提前致谢

【问题讨论】:

  • await & function (err, user) 彼此不兼容,.. IOW:如果您希望 mongoDb 使用 promise,请不要使用回调。例如。试试..const user = await User.findOne({ 'account': payload.data.account });
  • 我不使用 mongodb,我希望 save 也是异步的,.. 所以也许可以试试 await user.save(); 你也可以告诉我们你更新的代码,只是更新你的问题。
  • that the i changes before user.save,查看您修改后的代码,现在不应该发生这种情况。但无论如何我都会将var i 更改为let i,这将创建一个块范围的变量,因此即使您的异步操作不同步,我也不会丢失。
  • await 仅在函数返回承诺时有效。只是将var 更改为let 是虚拟解决方案,因为这将解决关闭而不是承诺的问题。阅读更多关于 async-await 和 promise 的内容。还要检查 user.save 和其他在 for 循环中调用的函数返回什么。
  • 你为什么要循环播放?在我看来,这只是一个简单的$push 操作与$each。显示您要更新的数据以及对文档所做的预期更改,您将专注于 Promise,而这不是实际需要解决的问题的一部分。

标签: javascript mongodb for-loop foreach async-await


【解决方案1】:

从我在这里看到的循环是完全不必要的。 MongoDB 有一个$push 运算符,它允许在不先检索文档的情况下更新数组。这还有一个$each 选项,允许在单个更新中“推送”元素列表。

简而言之,这只是一个向服务器发送请求并响应await:

// Transpose to array of objects for update
let availability = payload.data.start.map((e,i) =>
  ({ start: new Date(e+'Z'), end: new Date(payload.data.end[i] + 'Z') })
);

try { 
  // Perform the **one** update request
  let response = await User.updateOne(
    { 'account': payload.data.account },
    { '$push': { 'availability': { '$each': availability } } }
  );

  // maybe check the response
} catch(e) {
  // do something with any error
}

这就是你需要做的。无需“循环”,而且开销比来回到服务器检索文档并进行更改然后放回文档要少得多。

【讨论】:

    猜你喜欢
    • 2015-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    相关资源
    最近更新 更多