【问题标题】:Node.js Wait for nested promises with Promise.allNode.js 使用 Promise.all 等待嵌套的 Promise
【发布时间】:2018-12-02 11:00:45
【问题描述】:

我正在尝试等待循环中的所有数据库调用完成,然后再继续。我将每个调用(即承诺)添加到一个数组中,然后使用Promise.all() 等待所有调用。但是,有嵌套的 DB 调用,如 user.increment()user.create()Promise.all() 似乎并没有等待。这个 sn-p 的输出通常是:

User found, incrementing wins...
Promise.all()
User updated

Promise.all 块在嵌套 DB 调用完成之前运行。我觉得我错过了一些非常简单的东西。

let dbCalls = [];
for(var i = 0; i < users.length; i++){
    let messageUser = users[i];
    //try to find user by id
    dbCalls.push(db.user.findOne({
            where: {
                id: messageUser.id
            }
        }).then(function(user){
            if(user){
                //found user, increment them
                user.increment('wins').then((user) => {
                    console.log('User found, incrementing wins...');
                    user.reload();
                }).then(user => {
                    console.log('User updated')
                    return user;
                });
            } else{
                //user wasn't found, create them
                console.log(`${messageUser.username} was not found, creating user...`);
                db.user.create({
                    username: messageUser.username,
                    id: messageUser.id,
                    wins: 1
                }).then(function(user){
                    console.log('created user');
                    return user;
                });
            }
        }).then(res => {
            return res;
        })
    );
}

Promise.all(dbCalls).then(res =>{
    console.log('Promise.all()' + res);
});

【问题讨论】:

  • 你需要瀑布式调用,因为它们需要按顺序触发
  • 能否请您发布输出。
  • 除非您使用的是非常旧的节点版本,否则只使用let value = await doSomeFunction() 并继续下一行而不是到处都有.then() 更容易。

标签: javascript node.js promise


【解决方案1】:

你忘记兑现承诺了。所以它们不包含在你的承诺链中

只需将带有 db-promises 的行更改为 return user.increment('wins').then((user) =&gt; {

【讨论】:

    【解决方案2】:

    由于您正在运行多个数据库查询,需要一个在另一个之前完成,您应该查看 NODE.js 瀑布调用。它允许使用 Promise,并且您可以设置哪些 Promise 需要其他先完成,然后再触发。

    https://www.npmjs.com/package/promise-waterfall

    有一个很好的例子

    这个库甚至允许您等待返回值在另一个异步调用中使用。

    【讨论】:

      【解决方案3】:

      您需要链接所有内部承诺,以确保推送到数组的项目是完整的链。为了更好的可读性,请考虑将incrementcreate 提取到它们自己的函数中:

      const increment = user => user.increment('wins').then((user) => {
        console.log('User found, incrementing wins...');
        return user.reload();
      }).then(user => {
        console.log('User updated')
        return user;
      });
      const create = user => {
        //user wasn't found, create them
        console.log(`${messageUser.username} was not found, creating user...`);
        return db.user.create({
          username: messageUser.username,
          id: messageUser.id,
          wins: 1
        }).then(user => {
          console.log('created user');
          return user;
        });
      };
      
      const dbCalls = users.map(messageUser => db.user.findOne({
        where: {
          id: messageUser.id
        }
      }).then(user => (
        user
        ? increment(user)
        : create(user)
      )));
      
      Promise.all(dbCalls).then(res =>{
        console.log('Promise.all()' + res);
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-23
        • 2015-08-15
        • 2021-03-22
        • 1970-01-01
        • 1970-01-01
        • 2017-12-23
        • 2019-11-27
        相关资源
        最近更新 更多