在NodeJS中发送不同的POST响应

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在NodeJS中发送不同的POST响应相关的知识,希望对你有一定的参考价值。

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

我认为问题出在forcheckErrors循环中。由于你在循环中调用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()回调体外,它可能会在User.find()完成之前执行。这是使用Node.js进行异步编程的难点之一。当任务完成时,回调函数会发出信号,因此如果您没有在回调中包装想要连续的操作,则可以与源代码“无序”地执行。

另外,在函数registerUser中,如果user.save失败,那么客户端将永远不会知道,因为该函数为任何请求发送200状态代码。出现这种情况的原因与上面提到的相同:因为res.sendStatus(200)没有包含在user.save回调函数中,所以它可能在保存操作完成之前运行。如果在保存期间发生错误,您应该告诉客户端,可能使用500状态代码。例如:

var registerUser = function(req, res, user){
    user.save(function(err, user){
        if (err) {
            console.error(err);
            return res.status(500).send(err);
        }
        return res.sendStatus(201);
    });
};
另一答案

你对registerUser()的调用是在路线之后定义的,因为它不是一个悬挂的函数,所以它将是undefined。 你在封闭中使用scope是不正确的。对于您的特定错误,这是因为您在循环中运行res.send()时,它应该每个请求被调用一次(因此已经发送了已经发送的标题a.k.a.响应)。你也应该在调用res.send()之后直接从函数返回。

以上是关于在NodeJS中发送不同的POST响应的主要内容,如果未能解决你的问题,请参考以下文章

如何在多个异步调用中向 NodeJS 中的数据库发送响应?

在 NodeJs 中呈现 jquery POST 请求的响应

来自python的请求从nodejs得到不同的响应

异步响应到javascript NodeJS中的循环

Firefox 和 nodejs 的 jQuery Ajax POST 错误

axios post 请求挂在有效请求上