在NodeJS中发送不同的POST响应

时间:2015-09-30 23:37:35

标签: node.js post express error-handling

我想从以下问题中获得一些帮助。我正在撰写我的博士论文,而这一小部分代码将负责注册用户。 (我实际上是在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);
};

2 个答案:

答案 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()的来电是在路线之后定义的,并且undefinedscope,因为它不是一个悬挂的功能。
您在关闭中使用res.send()并不正确。对于您的具体错误,因为您在循环中运行res.send()时,每个请求只应调用一次(因此已经发送了已发送的标头a.k.a.响应)。您也应该在调用ChangePassword之后直接从函数返回。