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?
Advertisement
Answer
@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.