【问题标题】:Returning status when saving to mulitple dbs in one api call在一次 api 调用中保存到多个数据库时返回状态
【发布时间】:2020-05-12 06:31:43
【问题描述】:

我一直都是前端的人。 Latley,我一直在使用 Node.js 和 Mongoose 开发后端。当用户注册时,我想创建一个用户(用户 db),创建一个电子邮件令牌(emailToken db),然后以一种方法发送电子邮件......我什至不确定这是否是正确的方法它。

我一直很难说出这句话,所以请原谅我的脑残。我的问题是基于在调用该端点时返回一个状态。据我所知,只能返回一个状态,那么这里的 200 究竟是什么意思?在我的代码中,这意味着所有 3 件事都成功了吗?我觉得这种做法是错误的。在创建用户时可能会出现这种情况,但函数的其余部分失败......返回 400 或其他。这也不理想。从逻辑上讲,我想返回 200 用于创建用户,然后返回 200 用于创建电子邮件令牌,然后返回 200 用于成功发送电子邮件。

我将不胜感激。

  const user = new User(req.body);

  user
    .save()
    .then(user => {
      const emailToken = new EmailToken({
        _userId: user._id,
        token: crypto.randomBytes(16).toString("hex")
      });

      emailToken
        .save()
        .then(token => {
          const transporter = nodemailer.createTransport({
            service: "Sendgrid",
            auth: {
              user: USERNAME,
              pass: PASSWORD
            }
          });

          const mailOptions = {
            from: "XXXXXX@gmail.com",
            to: user.email,
            subject: "Account Verification Token",
            text:
              "Hello,\n\n" +
              "Please verify your account by clicking the link: \nhttp://" +
              req.headers.host +
              "/verify/" +
              token.token +
              ".\n"
          };

          transporter.sendMail(mailOptions, (err, info) => {
            if (err) {
              return res.status(409).send({
                user,
                error: "Could not send verification email. " + err.message
              });
            }

            res.status(200).send({
              user,
              token: token.token,
              success:
                "A verification email has been sent to " + user.email + "."
            });
          });
        })
        .catch(error => {
          res.status(409).send({
            user,
            message: "Could not send verification email."
          });
        });
    })
    .catch(error => {
      if (error.name === "MongoError" && error.code === 11000) {
        return res.status(400).send({
          success: false,
          message: "Username or email already exists."
        });
      }
      res.status(400).send(error);
    });
});

【问题讨论】:

    标签: node.js database express mongoose


    【解决方案1】:

    这里的 200 到底是什么意思?

    表示创建用户、生成token、发送邮件成功。

    我觉得这种做法是错误的。可能会出现创建用户但功能的其余部分失败的情况。

    您可以在电子邮件失败时删除用户

    我想为创建用户返回 200,然后为创建电子邮件令牌返回 200,为成功发送电子邮件返回 200。

    您只能发送一次响应,除非它是一个流。

    您可以将您的 Promise 重写为这样的内容,以提高可读性并防止回调地狱。你可以查看 promise-do-and-donts here

    const nodemailer_credentials = {
        service: "Sendgrid",
        auth: {
            user: USERNAME,
            pass: PASSWORD
        }
    };
    
    
    const user = new User(req.body);
    let _token, _user;
    
    user
        .save()
        .then(user => {
            _user = user;
    
            return new EmailToken({
                _userId: user._id,
                token: crypto.randomBytes(16).toString("hex")
            }).save();
        })
        .then(token => {
            _token = token;
            return nodemailer.createTransport(nodemailer_credentials);
        })
        .then(transporter => {
            return transporter.sendMail(mailOptions, (err, info) => {
                if (err) {
                    const mailError = new Error('MailerError');
                          mailError.details = `Could not send verification email. ${err.message}`
    
                    throw(mailError);
                }
                return;          
            });
        })
        .then(() => {
            res
                .status(200)
                .send({
                    user: _user,
                    token: _token.token,
                    success: `A verification email has been sent to ${user.email}.`
                })
        })
        .catch(error => {
            if (error.message === 'MailerError') {
                return res.status(400).send({
                    user: _user,
                    message: error.details
                });
            }
    
            if (error.name === 'MongoError' && error.code === 11000) {
                return res.status(400).send({
                    success: false,
                    message: `Username or email already exists.`
                });
            }
    
            res.status(400).send(error);
        });
    

    【讨论】:

    • 感谢您的解释。它真的帮助我了解如何剖析我的链条。我也没有意识到.catch() 实际上捕获了创建并沿着承诺链发送的错误。我只是认为这是一个通用的包罗万象。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    • 2019-06-11
    • 2020-04-13
    • 2021-08-20
    相关资源
    最近更新 更多