0

我是 node 新手,并且学习了所有关于 Promise 的知识,特别是 pg-promise。这就是我想要使用 Express 和 pg-promise 做的事情:

  1. 查看电子邮件,
  2. 如果找不到检查用户名,
  3. 如果没有找到创建一个新用户。
  4. 返回用户id

我已经设置了我的存储库(db.users),它执行的 sql 运行良好。

在我的授权处理程序中,我不确定如何使 repo 调用彼此跟随。语法对我来说似乎很笨拙。这是我到目前为止所拥有的:

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 不会像这样链接在一起?它们应该相互嵌套还是完全独立的块?此外,不太确定捕获的位置。按照各种教程,我已经尝试了所有我能想到的方法,但是我收到了诸如“无法设置已设置的标头”和“未返回承诺”之类的错误。如果有好心人可以在这里指导我,我将不胜感激。

4

3 回答 3

1

执行多个查询时必须使用 a 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所说的你应该做的事情。请参阅任务与根/直接查询

并且在进行多项更改时,您通常会使用事务 - 使用tx而不是task.

于 2017-02-02T08:35:12.760 回答
0

在vitally-t 的指导下,我改变了他的答案,根据失败的情况包含单独的错误消息。我还将下一个“then”上移到事务块中,以将事务的“t”用于创建用户的下一步。非常感谢vitally-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});
});
于 2017-02-02T21:10:35.940 回答
-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
  });

};
于 2017-02-02T04:51:28.637 回答