问题
Hello I am working in a user verification task using a middleware to verify if the user exist or not, this is my code:
I have an endpoint defined like this:
app.get("/login/", verifyUser, userController.login);
This is my middleware verifyUser:
function verifyUser(req, res, next) {
console.log("Midd 1:", req.query);
let userInfo = userController.findUserOne(req, res);
console.log("userInfo:" + userInfo);
next();
}
This is my controller method:
exports.findUserOne = function (req, res) {
(async () => {
try {
var query = db
.collection("users")
.where("user", "==", req.query.user)
.where("password", "==", req.query.password);
query.get().then(function (querySnapshot) {
if (querySnapshot.size > 0) {
const accessToken = generateAccessToken({ name: req.query.user });
res.json({ accessToken: accessToken });
} else {
return res.status(500).send("User doesn't exist:");
}
});
} catch {
return res.status(500).send(error);
}
})();
};
After calling the login endpoint I am getting the next error message:
(node:12468) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:485:11)
at ServerResponse.header (C:\Tools\Node\From Github\NodeAndReact-FullStack\server\node_modules\express\lib\response.js:771:10)
at ServerResponse.send (C:\Tools\Node\From Github\NodeAndReact-FullStack\server\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (C:\Tools\Node\From Github\NodeAndReact-FullStack\server\node_modules\express\lib\response.js:267:15)
at C:\Tools\Node\From Github\NodeAndReact-FullStack\server\controllers\users\userController.js:54:15
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:12468) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:12468) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I am handling my async block in the controller with a try, catch, but according to the looks it seems like the issue is related with that. In fact I'm not pretty sure if it is the best way to implement this verification or I am getting an issue related with the async code.
回答1:
The error Error [ERR_HTTP_HEADERS_SENT]
is occured when the response is already sent to the user. Here userController.findUserOne(req, res)
is async
. So js doesn't wait for it and next()
is called. This arises race conditions.
Middlewares aren't supposed to directly call controllers methods since these methods finally end up sending request to user. You can create a utils folder which can contain files to do all these logical stuff and return the data back to middelware and not send a response to user. Also, you need to chain with .then()
to wait for results and then call next()
in it.
But I guess you may want to shift all this logic to userController.login
. No separate middleware is required.
回答2:
it's because userController.findUserOne is an async function while you call it without any await behind it. so in this part of your code
function verifyUser(req, res, next) {
console.log("Midd 1:", req.query);
let userInfo = userController.findUserOne(req, res);
console.log("userInfo:" + userInfo);
next();
}
when you call userController.findUserOne(req, res);
since async functions return a promise, it will return a promise as well not the real user info you want.
the solution is to change verifyUser function to something like this:
async function verifyUser(req, res, next) {
try {
console.log("Midd 1:", req.query);
let userInfo = await userController.findUserOne(req, res);
console.log("userInfo:" + userInfo);
next();
} catch(error){
//handle exceptions here
}
}
来源:https://stackoverflow.com/questions/62856532/nodejs-unhandledpromiserejectionwarning-error-err-http-headers-sent-cannot-s