Search code examples
node.jsexpresscallbackfunctional-programmingpassport.js

return outter variable from callback is not work


I need to return result from userService.signIn() with new state but the return still { httpStatus: 500, message: undefined, errorMessage: undefined }

How can I get the current result?

{
  httpStatus: 200,
  message: {
    auth: true,
    token,
    message: 'user found & logged in' 
  }
}
// user-service.js

module.exports = (db) => {
  return {
    signIn: function (req, res, next) {
      const result = { httpStatus: 500, message: undefined, errorMessage: undefined };
      passport.authenticate('local-comparePassword', {}, (err, user, info) => {
        if (err) {
          console.error(err);
        }
        if (info !== undefined) {
          console.error(`Info Message Error: ${info.message}`);
          if (info.message !== 'Username or Password is incorrect') {
            console.log(info.message)
            result.httpStatus = 401;
            result.errorMessage = info.message;
          } else if (!user) {
            console.log(info.message)
            result.httpStatus = 204;
            result.message = 'User not found';
          } else {
            console.log(info.message)
            result.httpStatus = 400;
            result.errorMessage = info.message;
          }
        } else {
          const token = jwt.sign(
            { id: user.id, role: user.role, name: user.name },
            jwtOptions.secretOrKey,
            { expiresIn: 3600 }
          );

          result.httpStatus = 200;
          result.message = {
            auth: true,
            token,
            message: 'user found & logged in'
          };
        }
        return result;
      })(req, res, next);

      // return result
    },
  }
}
// user-controller.js
module.exports = (db) => {
  return {
    signIn: async (req, res, next) => {
      try {
        const result = await userService(db).signIn(req, res, next)
        console.log('result', result) **// result undefined**
        if (res.httpStatus === 200 || result.httpStatus === 400 || result.httpStatus === 401) {
          res.status(result.httpStatus).json({ message: result.message });
        } else {
          res.status(result.httpStatus).json({ errorMessage: 'error' });
        }
      } catch (ex) {
        console.log(ex.message);
        res.status(400).json({ errorMessage: ex.message })
      }
    }
  }
}

Solution

  • Did not run your code, but as I see it:

    1. Why did your commented out return result in userService().signIn() ? Thus // result undefined. Ok, let's assume that your code is a little bit out of sync with your question.
    2. But if your will return result from userService().signIn() (as you should) it will be in no vain - passport.authenticate() calls your callback asynchronously after userService().signIn() returns
    3. return result inside of passport.authenticate() callback will return result to passport.authenticate(), not to your userService().signIn(), and again, it will happen after signIn returns
    4. Your must declare signIn as async function(...) - there is no sense in await with a function that do not return a Promise
    5. For that you also need to convert passport.authenticate() itself into an async function. Something like this:
      new Promise((resolve, reject) => {
          passport.authenticate(..., (err, user, info) => {
              // ...
              if (err) reject(err);
              if (user) resolve(user);
          }
      }
      
    6. and then you can
      signIn: async function(req, res, next) {
        const result = { httpStatus: 500, message: undefined, errorMessage: undefined }
        return await new Promise((resolve, reject) => {
          passport.authenticate(..., (err, user, info) => {
            // ...
            resolve(result);
          }
        }
      }
      
      and then
      await userService(db).signIn()