我想从以下问题中获得一些帮助。我正在撰写我的博士论文,而这一小部分代码将负责注册用户。 (我实际上是在nodejs的新手)。我也使用快递和猫鼬。
我想处理请求数据,并检查一些错误,首先我想检查是否所有字段都存在,其次,如果有人已经注册了这个电子邮件地址。
根据错误(或成功),我想发送不同的回复。如果一个字段丢失,那么400 Bad请求(如果用户存在)则409 Conflict,200 OK,如果一切正常。但是我只想在没有错误的情况下进行回调,但我有点卡在这里...我得到错误发送后不能设置标题,这实际上很明显,因为JS即使设置了响应,也会继续处理代码。
app.post('/register', function (req, res) {
var user = new User(req.body);
checkErrors(req, res, user, registerUser);
});
var registerUser = function(req, res, user){
user.save(function(err, user){
if (err) return console.log(err);
});
res.sendStatus(200);
};
var checkErrors = function(req, res, user, callback){
var properties = [ 'firstName', 'lastName', 'email', 'password', 'dateOfBirth' ];
for(var i = 0; i < properties.length; i++){
if(!req.body.hasOwnProperty(properties[i])){
res.status(400).send('field ' + properties[i] + ' not found');
}
}
var criteria = {
email: req.body.email
};
User.find(criteria).exec(function(err, user){
if(user.length > 0){
res.status(409).send('user already exists');
}
});
callback(req, res, user);
};
答案 0 :(得分:0)
我认为问题出在for
的{{1}}循环中。由于您在循环中调用checkErrors
,因此最终可以多次调用它,这将在第一次调用后触发错误,因为响应已经被发送回客户端。
在循环中,您可以将缺少的字段添加到数组中,然后检查数组的长度以查看是否应该使用res.status(400).send()
或继续进行响应。这样,您只能拨打400
一次。
例如:
res.status(400).send()
一般情况下,我建议您将...
var missingFields = [];
for(var i = 0; i < properties.length; i++){
if(!req.body.hasOwnProperty(properties[i])){
missingFields.push(properties[i]);
}
}
if(missingFields.length > 0) {
return res.status(400).send({"missingFields" : missingFields});
}
...
放在每个return
来电之前,以确保以后不会意外调用其他人。
这方面的一个例子是:
res.send()
您可能已经注意到我移动了User.find(criteria).exec(function(err, user){
// We put return here in case you later add conditionals that are not
// mutually exclusive, since execution will continue past the
// res.status() call without return
if(user.length > 0){
return res.status(409).send('user already exists');
}
// Note that we also put this function call within the block of the
// User.find() callback, since it should not execute until
// User.find() completes and we can check for existing users.
return callback(req, res, user);
});
。如果我们将callback(req, res, user)
留在callback(req, res, user)
回调的正文之外,则有可能在User.find()
完成之前执行它。这是使用Node.js进行异步编程的难点之一。当任务完成时,回调函数会发出信号,因此可以执行&#34;无序&#34;如果你没有包装想要在回调中顺序的操作,则与你的源代码有关。
另一方面,在函数User.find()
中,如果registerUser
失败,那么客户端永远不会知道,因为函数会为任何请求发送user.save
状态代码。出现这种情况的原因与我上面提到的相同:因为200
没有包含在res.sendStatus(200)
回调函数中,所以它可能在保存操作完成之前运行。如果在保存期间发生错误,您应该告诉客户端,可能是user.save
状态代码。例如:
500
答案 1 :(得分:0)
您对registerUser()
的来电是在路线之后定义的,并且undefined
是scope
,因为它不是一个悬挂的功能。
您在关闭中使用res.send()
并不正确。对于您的具体错误,因为您在循环中运行res.send()
时,每个请求只应调用一次(因此已经发送了已发送的标头a.k.a.响应)。您也应该在调用ChangePassword
之后直接从函数返回。