I am creating a REST API with express, folowing are my architecture,a router is calling a controller.but I got this error, please help me
Error: Route.post() requires a callback function but got a [object Promise]
/////// EmailLogin.js middleware Handler
const { validationResult } = require('express-validator');
let wrapRoute = async (req, res, next) => {
try {
// run controllers logic
await fn(req, res, next)
} catch (e) {
// if an exception is raised, do not send any response
// just continue performing the middleware chain
next(e)
}
}
const EmailLogin = wrapRoute(async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
} else {
var gtoken = req.body.gtoken;
var gSecretKey = env.secret_key;
if (!gtoken) throw new Error('no token')
const captchaURL = `https://www.google.com/recaptcha/api/siteverify?secret=${gSecretKey}&response=${gtoken}`
await axios({
url: captchaURL,
method: 'POST',
headers: {ContentType: 'application/x-www-form-urlencoded'},
}).then(response => {
const gVerifyData = response.data
if (gVerifyData.success === true) {
Users.findOne({'email': req.body.email}).select(' hashPassword status').exec(function (err, user) {
if(err){
return res.status(500).send({err});
} else if (user) {
validPassword = bcrypt.compareSync(req.body.password, user.hashPassword);
if (!validPassword){
return res.send("wrong-info");
} else if (validPassword && user.status == "active") {
token = jwt.sign({ id: user._id }, env.jwtsecret,
{ expiresIn: "168h" });
res.status(200).send({ token: token, user });
}
} else {
return res.send("wrong-info");
}
}
)
}else {
return res.status(500).send('bot');
}
}).catch(error => {
console.log(error);
});
}
});
function errorHandler (err, req, res, next) {
console.log(err);
// If err has no specified error code, set error code to 'Internal Server Error (500)'
if (!err.statusCode) {
err.statusCode = 500;
}
res.status(err.statusCode).json({
status: false,
error: err.message
});
};
module.exports = {EmailLogin};
I'm trying to call it in my router, like this:
/////// Router.js
const express = require('express');
const router = express.Router();
const { check } = require('express-validator');
const EmailLoginController = require('../controllers/EmailLogin');
var emailLoginValidation = [
check('email').notEmpty().trim().escape().isEmail(),
check('password').notEmpty().isLength({ min: 7 }).withMessage('password is invalid'),
];
router.post('/email-login', emailLoginValidation, EmailLoginController.EmailLogin);
module.exports = router;
/////// App.js
var express = require("express");
var app = express();
const Router = require('./routes/Router');
app.use('/', Router);
app.listen(3000, function() {
console.log('listening on 3000');
});
What could I do ? is it possible to get a Promise Result in the Router as a Handler?
CodePudding user response:
@turkdev Change your email login function to this
const EmailLogin = async (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
} else {
var gtoken = req.body.gtoken;
var gSecretKey = env.secret_key;
if (!gtoken) throw new Error('no token')
const captchaURL = `https://www.google.com/recaptcha/api/siteverify?secret=${gSecretKey}&response=${gtoken}`
await axios({
url: captchaURL,
method: 'POST',
headers: { ContentType: 'application/x-www-form-urlencoded' },
}).then(response => {
const gVerifyData = response.data
if (gVerifyData.success === true) {
Users.findOne({ 'email': req.body.email }).select(' hashPassword status').exec(function (err, user) {
if (err) {
return res.status(500).send({ err });
} else if (user) {
validPassword = bcrypt.compareSync(req.body.password, user.hashPassword);
if (!validPassword) {
return res.send("wrong-info");
} else if (validPassword && user.status == "active") {
token = jwt.sign({ id: user._id }, env.jwtsecret,
{ expiresIn: "168h" });
res.status(200).send({ token: token, user });
}
} else {
return res.send("wrong-info");
}
}
)
} else {
return res.status(500).send('bot');
}
}).catch(error => {
console.log(error);
});
}
};
The problem was earlier, you were assigning it to method wrapRoute() which returns a Promise, which was not settled, causing the error which you got.
If that was just for calling next() on error, you could always use it in the catch block.