Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

done() vs return done()

Tags:

I was reading the docs for passport and I noticed that with serialize() and deserialize() done() is called with out being returned.

However when setting up a new strategy using passport.use() in the callback function return done() is used.

Is this something that needs to be understood or just copied from the docs?

http://www.passportjs.org/docs/

From the docs:

var passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function (err, user) {
      if (err) { return done(err); }
      if (!user) {
        return done(null, false, { message: 'Incorrect username.' });
      }
      if (!user.validPassword(password)) {
        return done(null, false, { message: 'Incorrect password.' });
      }
      return done(null, user);
    });
  }
));
like image 881
jennifer Avatar asked Jan 06 '20 20:01

jennifer


People also ask

What is done () in Javascript?

done() returns the deferred object, other methods of the deferred object can be chained to this one, including additional . done() methods. When the Deferred is resolved, doneCallbacks are executed using the arguments provided to the resolve or resolveWith method call in the order they were added.

Why We Use done ()?

The testing framework needs to know when the asynchronous operation is finished so it can check that the test passed. So it gives you a done() function that you call to let it know.

What is done function in Nodejs?

The done function must be called when it has finished handling the message. It takes one optional argument, an error object if the node has failed to handle the message for some reason.

What does the done function in Passport strategy verify callback function do?

This is possible with the help of done() function. It is an internal passport js function that takes care of supplying user credentials after user is authenticated successfully. This function attaches the email id to the request object so that it is available on the callback url as "req.


1 Answers

return done() will cause the function to stop executing immediately. This means that any other lines of code after that line inside the function will be ignored and not evaluated.

done() not preceded by return, however, will not cause the function to stop executing. This means that any other lines of code after that line inside the function will be evaluated.

If you take a look at this passport.use() example (from the Passport docs), you'll see there is reachable code after the first three return done() statements, and you would want the function to exit immediately as soon as done() is called the first time to make sure none of the following instructions are evaluated:

passport.use(new BasicStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function (err, user) {
      if (err) { return done(err); } 
      if (!user) { return done(null, false); }
      if (!user.validPassword(password)) { return done(null, false); }
      // The following line is the success case. We do not want to execute it
      // if there was an error, a falsy user or a user without a valid 
      // password. If we removed the return keywords from the previous lines
      // of code, the success case would be triggered every time this
      // function was called
      return done(null, user);
    });
  }
));

Here I've added two executable snippets to illustrate the difference between done() and `return done(). The snippets are otherwise identical.

done() without return:

const done = console.log

const assessThreatLevel = threatLevel => {
  if (threatLevel === 'all good') done('relax :)')
  done('launch the missiles!')
}

assessThreatLevel('all good')

`return done():

const done = console.log

const assessThreatLevel = threatLevel => {
  if (threatLevel === 'all good') return done('relax :)')
  done('launch the missiles!')
}

assessThreatLevel('all good')

As an aside, I have taken to using return done() in most situations for consistency. As far as I'm aware, there's no drawback to using it. It can help you avoid bugs, and the return statement serves as a guarantee and a good visual reminder that the function will exit immediately after that statement is evaluated.

like image 121
tex Avatar answered Sep 30 '22 19:09

tex