node.js - 在一次 api 调用中保存到多个数据库时返回状态
问题描述
我一直是一个前端的人。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);
});
});
解决方案
200 在这里实际上意味着什么?
表示创建用户、生成token、发送邮件成功。
我觉得这种做法是错误的。在创建用户但功能的其余部分失败的情况下可能会出现这种情况。
您可以在电子邮件失败时删除用户
我觉得我想为创建用户返回 200,然后为创建电子邮件令牌返回 200,为成功发送电子邮件返回 200。
您只能发送一次响应,除非它是一个流。
您可以将您的承诺重写为这样的内容,以提高可读性并防止回调地狱。你可以在这里查看 promise-do-and-donts
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);
});
推荐阅读
- go - 如何在 go testing 中仅重新运行失败的测试
- swift - 通过 CNContactStore 枚举联系人时的公司字段
- git - git push: 致命:远程端意外挂断 远程主机关闭与 github.com 的连接
- websocket - Tradier API websockets 流 node.js 示例未接收任何事件
- r - 使用 data.table 在 R 中创建开发图
- javascript - jquery ui autocomplete Uncaught TypeError:无法读取未定义的属性'0'
- mysql - 我怎样才能知道 MySQL 中的约束名称(由我们提供)?
- oracle - 存储过程在参数声明中调用 2 个值
- c# - EF Core - FromSql 在参数化数字集合时抛出无效数字
- reactjs - 我不知所措:第 35:9 行:解析错误:预期对应的 JSX 结束标记