如何使用promises将语句链接在一起

时间:2017-02-02 03:09:40

标签: node.js express pg-promise

我是节点的新手,并且学习所有关于承诺的内容,特别是pg-promise。这就是我想用Express和pg-promise做的事情:

  1. 查看电子邮件,
  2. 如果找不到则检查用户名,
  3. 如果找不到则创建新用户。
  4. 返回用户ID
  5. 我已经设置了我的repo(db.users),这使得sql工作得很好。

    在我的授权处理程序中,我不确定如何让回购电话互相跟随。语法对我来说似乎很笨拙。这就是我到目前为止所拥有的:

    exports.signup = function( req, res, next ) {
    
    const username = req.body.username;
    const email = req.body.email;
    const password = req.body.password;
    
     // See if a user with the given email exists
         db.users.byEmail({email: email})
          .then(user => {
            if (user) {
             return res.status(422).send({ error: 'Email is in use'});
           } else { 
             return null;   <-- must I return something here?
           }
          })
       .then(() => {
         db.users.getUsername({username: username})
         .then(user => {
            if (user) {
             return res.status(422).send({ error: 'Email is in use'});
           } else { 
             return null;   <-- must I return something here?
           }
    
           ...etc
    
       })
    

    也许pg-promises不会像这样链接在一起?它们应该嵌套在一起还是完全独立的块?此外,不太确定捕获的位置。我已经按照各种教程尝试了各种方式,但是我遇到了错误,例如“无法设置已设置的标头”。并且承诺不会被退回&#39;。如果有任何善良的人可以在这里指导我,我真的很感激。

3 个答案:

答案 0 :(得分:1)

执行多个查询时必须使用task,这样他们就可以共享一个连接,否则连接管理会遇到性能问题。

db.task(t => {
    return t.users.byEmail({email})
        .then(user => {
            return user || t.users.getUsername({username});
        });
})
    .then(user => {
        if (user) {
            res.status(422).send({error: 'Email is in use'});
        } else {
            // do something else
        }
    })
    .catch(error => {
        // process the error
    });

它会很好用,假设您的存储库设置如pg-promise-demo所示。

之前的2个答案真的很糟糕,完全反对pg-promise你应该做的事情。请参阅Tasks versus root/direct queries

进行多项更改时,通常会使用交易 - 使用tx代替task

答案 1 :(得分:0)

在vitaly-t的指导下,我改变了他的答案,根据失败的内容包含单独的错误消息。我也提升了下一个&#34;然后&#34;进入事务块以使用&#34; t&#34;用于创建用户的下一步的事务。非常感谢vitaly-t!

db.task(t => {
    return t.users.byEmail({email})
      .then(user => {
          if (user) {
            throw new Error('Email is in use');
          } else {
            return t.users.byUsername({username});
        }
      })
      .then((user) => {
          if (user) {
              throw new Error('Username is taken');
          } else {
              return t.users.addNew({username, email, password});
          }
      })
})
.then(user => {
    res.json({token: tokenForUser(user), username: user.username, aCheck: user.is_admin});
})
.catch(error => {
    res.status(422).json({ 'error': error.message});
});

答案 2 :(得分:-1)

检查usernameemail存在是否相互独立。我认为Promise.all()将比顺序链接承诺更符合您的需求。

exports.signup = function (req, res, next) {
  const username = req.body.username;
  const email = req.body.email;
  const password = req.body.password;

  Promise.all([
    db.users.byEmail({
      email: email
    }),
    db.users.getUsername({
      username: username
    })
  ]).then((results)=> {
    if (results[0] || results[1]) {
      return res.status(422).send({
        error: 'Email is in use' // same error msg as per your snippet
      });
    }
    // here, code for creating a new user
  });

};