链接多个Promises,使用map遍历数组并创建猫鼬文档?

时间:2020-06-18 17:16:32

标签: node.js arrays mongoose promise

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

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

1 个答案:

答案 0 :(得分:1)

那是因为Promise.all只是在等待您mapping的所有承诺。它不保证兑现承诺的任何顺序。

如果要顺序顺序处理res数组的元素,则可以简单地将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;
}