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);
});
}
));
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With