Reputation: 1926
I'm trying to make an API for learning purpose. There's nothing wrong with the API. I get the response I want. But the problem is, when I look at the terminal, I get an error like this:
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().
It warn me that permission rejection are not handled will terminate the Node.js.
Console LOG
(node:8721) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:526:11)
at ServerResponse.header (/backend/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/backend/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/backend/node_modules/express/lib/response.js:267:15)
at exports.apiFormat (/backend/handlers/errorHandlers.js:85:21)
at /backend/middlewares/auth.js:31:11
at allFailed (/backend/node_modules/passport/lib/middleware/authenticate.js:107:18)
at attempt (/backend/node_modules/passport/lib/middleware/authenticate.js:180:28)
at Strategy.strategy.fail (/backend/node_modules/passport/lib/middleware/authenticate.js:302:9)
at verified (/backend/node_modules/passport-local/lib/strategy.js:82:30)
at /backend/middlewares/passport.js:69:24
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:8721) 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(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:8721) [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 make it for same json resonse format api. ( errorHandlers.js)
exports.apiFormat = (statusCode, responseCode, message, success, data, res) => {
try {
return res.status(statusCode).json({
message: message,
success: Boolean(success),
data: data,
status: Number(responseCode),
});
} catch (error) {
res.status(500).json({
message: "Internal Server Error",
});
}
};
Middleware for Authentication using passport.js auth.js
exports.login = async (req, res, next) => {
try {
await validateField(req, res);
await passport.authenticate("login", async (err, user) => {
if (err || !user) {
apiFormat(
process.env.UNAUTORIZED_CODE,
process.env.FAILURE_RESPOSNE_CODE,
"Authentication Failed.",
false,
null,
res
);
}
try {
req.login(user, { session: false }, (err) => {
if (err) {
apiFormat(
process.env.UNAUTORIZED_CODE,
process.env.FAILURE_RESPOSNE_CODE,
"Authentication Failed.",
false,
null,
res
);
}
const tokenData = {
id: user.id,
name: user.name,
email: user.email,
role: user.role,
};
const accessToken = jwt.sign(
tokenData,
"access_token",
{
expiresIn: "8h",
}
);
tokenData.accessToken = accessToken;
req.tokenData = tokenData;
});
} catch (error) {
next(error);
}
next();
})(req, res, next);
} catch (error) {
next(error);
}
//Validate Userinput Field
};
I use express-validator to validate the post data.
validateField(req, res)
const { validationResult } = require("express-validator"); const { apiFormat } = require("../handlers/errorHandlers"); exports.validateField = async (req, res) => { try { const errors = await validationResult(req); const extractedErrors = []; if (!errors.isEmpty()) { errors .array({ onlyFirstError: true }) .map((err) => extractedErrors.push(err.msg)); } if (extractedErrors.length > 0) await apiFormat( process.env.UNPROCESSABLE_ENTITY_CODE, process.env.FAILURE_RESPOSNE_CODE, extractedErrors[0], false, null, res ); } catch (err) { res.status(500).json({ message: "Internal Server Error", }); } };
passport.js:
passport.use(
"login",
new LocalStrategy(
{
usernameField: "email",
passwordField: "password",
session: false,
},
(email, password, done) => {
try {
User.findOne({
email: email,
})
.then((user) => {
if (user === null) {
return done(null, false);
}
bcrypt.compare(password, user.password).then((response) => {
if (response !== true) {
return done(null, false);
}
return done(null, user);
});
})
.catch((err) => {
return done(err);
});
} catch (err) {
return done(err);
}
}
)
);
Api route
router.post(
"/login",
validator.loginUser,
auth.login,
catchErrors(userController.login)
);
validator.loginUser
exports.loginUser = [
check("email")
.exists()
.withMessage("Email is required")
.isEmail()
.normalizeEmail()
.withMessage("Please insert a valid Email"),
check("password")
.not()
.isEmpty()
.withMessage("Password is required")
.isLength({ min: 8 })
.withMessage("Please enter password with minimum 8 character")
.trim()
.escape(),
];
Can you please tell me where i am wrong? And why i am getting such error UnhandledPromiseRejectionWarning?
Upvotes: 0
Views: 16590
Reputation: 2008
validationResult()
Returns the result object but not promise. You are using await
to wait for a Promise object.
Remove await
from your code to prevent the error:
const errors = validationResult(req);
// .. and your error variable will have arrays of error.
Upvotes: 1