链接多个 Promise,使用 map 循环数组并创建 mongoose 文档?

Posted

技术标签:

【中文标题】链接多个 Promise,使用 map 循环数组并创建 mongoose 文档?【英文标题】:Chaining multiple Promises, loop over array using map and create mongoose document? 【发布时间】:2020-10-08 20:18:30 【问题描述】:

我正在使用getPeople() 从数据库中检索人员列表。一旦我以res 收到它们,我想准备将它们存储在我的本地 mongodb 如果它们不存在。有时res 中有重复的条目(对于一个id)。我的问题是它没有等待Person.create(pers) 完成,继续搜索这个id 是否已经在mongodb 中,找不到任何因为Person.create(pers) 仍在创建它并开始第二个Person.create(pers)..

this.getPeople()
  .then(res => 
    return Promise.all(res.map(pers => 
      pers.birthday = df(pers.birthday, 'dd.mm.yyyy')
      pers.pickedUp = false
      console.log(pers.id)
      return Person
        .find( id: pers.id )
        .exec()
        .then(found => 
          if (found === undefined || found.length == 0)
            return pers
        )
        .then(pers => 
          return Person
            .create(pers)
            .then(console.log('created'))
            .catch(err => console.log(err))
        )
    ))
  ).catch(err => console.log(err))

我希望控制台输出是这样的:

940191
created
940191
created

相反,我得到了这个:

940191
940191
created
created

【问题讨论】:

【参考方案1】:

那是因为 Promise.all 只是在等待你的所有承诺 mapping。它不保证承诺的解决顺序。

如果您想按顺序处理res-array 的元素,您可以简单地将for .. of 循环与async/await 结合使用(请注意,这仍然需要一些错误处理,但它应该给你一些东西开始):

async function getPeopleAndCreateIfNotExisting() 
    const persons = [];
    const res = await this.getPeople();

    for (const pers of res)     
        pers.birthday = df(pers.birthday, 'dd.mm.yyyy');
        pers.pickedUp = false;
        console.log(pers.id)
        const found = await Person
            .find( id: pers.id ).exec();
        if (found) 
            persons.push(pers);
         else 
            persons.push(await Person.create(pers));
        
    
    return person;

【讨论】:

这有帮助,谢谢。最后我做了不同的事情,但类似于你的建议。 :) 太好了,乐于助人! :)

以上是关于链接多个 Promise,使用 map 循环数组并创建 mongoose 文档?的主要内容,如果未能解决你的问题,请参考以下文章

解决for循环中异步请求顺序不一致的问题

在map函数中使用axios时返回一个promise数组?

链接数组方法(filter、map、reduce)而不是使用双循环

然后使用数组链接 [重复]

在 PromiseKit 6 中正确链接多个 Promise

Promise循环执行多个请求