Skip to content
Advertisement

Error: Route.post() requires a callback function but got a [object Promise]

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.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement