我使用NodeJS创建一个API,使用快速框架和mongodb来存储我的数据。
我有一个寄存器功能,可以做三件事。
发送电子邮件。
module.exports.register = function(req,res){
var input = req.body;
var token = uuid.v4();
// Create a new user
var user = new User ({
username: input.username,
email: input.email,
password: input.password,
active: false
});
user.save(function(err) {
if(err) return res.json({success: false, errors: 'Failed To Create User'});
});
// Create a new Token
var newToken = createToken('new', null, user._id);
// Assign New Token To New User
if(newToken) {
user.tokens.push(newToken._id);
user.save(function(err) {
if(err) return res.json({success: false, errors: 'Failed To Save User Token'});
});
}
// Send Email To User
var mailData = {
from: 'deleted@hotmail.com',
to: input.email,
subject: 'Activate Your Account',
text: 'http://localhost:8080/api/auth/activate/' + token
}
mail.messages().send(mailData, function(err, body) {
if(err) return res.json({ success: false, errors: 'Failed To Send Email' });
});
return res.json({
success: true,
status: 'Successfully Registered User, Check Email To Activate'
});
}
现在即使在创建用户或令牌或发送电子邮件时出现错误。它总是会返回它成功注册用户。我怎样才能更好地重组/处理这个?
我还有一个问题,如果电子邮件无法发送用户并且已经创建了令牌,我该如何解决这个问题?我会创建重发激活功能吗?
答案 0 :(得分:1)
您提到它总是会返回它已成功注册用户。即使令牌创建失败,它也会发送电子邮件。
一种(不是很漂亮)的方法是继续上一步回调函数中的下一步:
user.save(function(err) {
if(err) {
return res.json({success: false, errors: 'Failed To Create User'});
} else {
// Create a new Token
var newToken = createToken('new', null, user._id);
// Assign New Token To New User
if(newToken) {
user.tokens.push(newToken._id);
user.save(function(err) {
if(err) {
return res.json({success: false, errors: 'Failed To Save User Token'});
} else {
// Send Email To User
var mailData = {
from: 'deleted@example.com',
to: input.email,
subject: 'Activate Your Account',
text: 'http://localhost:8080/api/auth/activate/' + token
}
mail.messages().send(mailData, function(err, body) {
if(err) {
return res.json({ success: false, errors: 'Failed To Send Email' });
} else {
return res.json({
success: true,
status: 'Successfully Registered User, Check Email To Activate'
});
}
});
}
});
}
}
});
正如您所看到的,它看起来像一个非常快速的回调-piramyd-of-doom,但它只在完成所有前面的步骤后发送成功响应。
您还应该在未创建newToken
时添加else案例。
答案 1 :(得分:0)
如果没有错误,你应该删除final return语句(从你的代码末尾开始)并返回每个回调内的正确位置。
如果您在函数正文中发送响应,则回调将永远无法运行。因此,您必须嵌套回调,并且只有在
时才调用res.send
e.g。
// Create a new user
var user = new User ({
username: input.username,
email: input.email,
password: input.password,
active: false
});
user.save(function(err) {
if(err) return res.json({success: false, errors: 'Failed To Create User'});
// Create a new Token
var newToken = createToken('new', null, user._id);
// Assign New Token To New User
if(newToken) {
user.tokens.push(newToken._id);
user.save(function(err) {
if(err) return res.json({success: false, errors: 'Failed To Save User Token'});
// Send Email To User
var mailData = {
from: 'deleted@hotmail.com',
to: input.email,
subject: 'Activate Your Account',
text: 'http://localhost:8080/api/auth/activate/' + token
}
mail.messages().send(mailData, function(err, body) {
if(err) return res.json({ success: false, errors: 'Failed To Send Email' });
return res.json({
success: true,
status: 'Successfully Registered User, Check Email To Activate'
});
});
});
}
});
不幸的是,对于node.js,你应该习惯并理解回调;即使你最终在大部分时间都使用其他东西。您的代码的结构方式更整洁,但在node.js中不起作用,因为您必须等待回调完成才能从函数返回。
但是,回调是默认值,但却是处理异步逻辑的最糟糕机制之一。如果您想以不同的方式构建代码,那么您有很多选择。这里只是一对:
在您的情况下,您的数据库库(mongoose?sequelize?)应该内置一些允许您编写代码的内容:
user.save()
.then(function () {
// step 1
})
.then(funciton () {
// step 2
})
.done()
这种编程风格非常值得学习,它将使您的代码比回调更具可读性。 callbacks vs promises
// this is just an example
var result = user.save();
if (result.error) return res.send({success : false, ...});
user.token = getNewToken();
user.update();
if (result.error) return res.send({success : false, ...});
return res.send({success : true, message : "Good news, no errors"});
生成器/(又称异步函数)是Javascript移动的方向,但是有一个学习曲线可以开始使用。在幕后,有一些非常复杂的事情要使异步代码看起来像同步代码。基本上,这些函数知道如何暂停执行,直到再次需要它们为止。
就像我说的那样,回调并不是那么好。但是,您应该习惯使用它们。它们是node.js的基本构建块,需要一段时间才能获得更好的替代方案。习惯它们也很重要,否则你不会理解为什么替代品更好。
祝你好运并注意循环中的回调:)