for循环内的异步功能

时间:2018-11-02 19:08:18

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

我正在构建应用程序,并且在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应用于此数组。但是我不认为这种解决方案是更可取的。 有任何想法吗?预先感谢

1 个答案:

答案 0 :(得分:2)

从这里我可以看到,循环是完全不必要的。 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
}

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