58

I have a function inside an if statement

isLoggedin() has an async call.

router.get('/', function(req, res, next) {
    if(req.isLoggedin()){ <- never returns true
        console.log('Authenticated!');
    } else {
        console.log('Unauthenticated');
    }
});

how do i await for isLoggedin() in this if statement?

here is my isLoggedin function in which im using passport

app.use(function (req, res, next) {
   req.isLoggedin = () => {
        //passport-local
        if(req.isAuthenticated()) return true;

        //http-bearer
       passport.authenticate('bearer-login',(err, user) => {
           if (err) throw err;
           if (!user) return false;
           return true;

       })(req, res);
   };

   next();
});
Saksham
  • 9,037
  • 7
  • 45
  • 73
pfMusk
  • 769
  • 1
  • 7
  • 16

2 Answers2

89

I do this exact thing using async/await in my games code here

Assuming req.isLoggedIn() returns a boolean, it's as simple as:

const isLoggedIn = await req.isLoggedIn();
if (isLoggedIn) {
    // do login stuff
}

Or shorthand it to:

if (await req.isLoggedIn()) {
    // do stuff
} 

Make sure you have that inside an async function though!

Sterling Archer
  • 22,070
  • 18
  • 81
  • 118
  • is there a way to use process.nextTick() instead? because i want to keep my syntax if(req.isLoggedin()){} – pfMusk Jan 29 '18 at 18:57
  • Any particular reason why? I don't think synchronizing to the next event loop has a benefit over a Promise – Sterling Archer Jan 29 '18 at 18:58
  • because i want to keep my syntax if(req.isLoggedin()){} :) would it be much more inefficient? – pfMusk Jan 29 '18 at 19:00
  • The efficiently would be negligible, but `nextTick` does hold a higher efficiency because Promises create 2 and throws away one, but tbh I've never used nextTick to handle async behavior and I don't really know too many who do. I'll have to do some more research – Sterling Archer Jan 29 '18 at 19:02
  • 13
    @pfMusk **Please** don't use process.nextTick for this. Just make the function `async` and use `await`, you-in-6-months would thank you. – Madara's Ghost Jan 29 '18 at 19:04
  • okok thank you @MadaraUchiha – pfMusk Jan 29 '18 at 19:51
  • This answer is wrong. Putting `await` before a function call that returns a boolean, will not await the asynchronous `authenticate` process that the Asker has. I don't understand why this was marked as accepted. – trincot Dec 28 '21 at 12:11
13

You could promisify your function, like this:

req.isLoggedin = () => new Promise((resolve, reject) => {
    //passport-local
    if(req.isAuthenticated()) return resolve(true);

    //http-bearer
   passport.authenticate('bearer-login', (err, user) => {
       if (err) return reject(err);
       resolve(!!user);
   })(req, res);
});

And then you can do:

req.isLoggedin().then( isLoggedin => {
    if (isLoggedin) {
        console.log('user is logged in');
    }
}).catch( err => {
    console.log('there was an error:', err); 
});

Do not try to keep the synchronous pattern (if (req.isLoggeedin())), as it will lead to poorly designed code. Instead, embrace fully the asynchronous coding patterns: anything is possible with it.

trincot
  • 317,000
  • 35
  • 244
  • 286