Refactor passport local strategy using promisy. Problem with .catch()
up vote
0
down vote
favorite
In an express + passport + local strategy app, I use bcrypt to hash password, this is working:
var bcrypt = require('bcrypt-nodejs');
familySchema.pre('save', function(next) {
var family = this;
var SALT_FACTOR = 14;
if (!family.isModified('password')) return next();
bcrypt.genSalt(SALT_FACTOR, function(err, salt) {
if (err) return next(err);
bcrypt.hash(family.password, salt, null, function(err, hash) {
if (err) return next(err);
family.password = hash;
next();
});
});
});
Then I refactored using promisify and async/await:
const bcrypt = require('bcrypt-nodejs');
const util = require('util');
const bcryptGenSalt = util.promisify(bcrypt.genSalt);
const bcryptHash = util.promisify(bcrypt.hash);
familySchema.pre('save', async function(next) {
var family = this;
const SALT_FACTOR = 14;
if (!family.isModified('password')) return next();
const salt = await bcryptGenSalt(SALT_FACTOR).catch(next);
const hash = await bcryptHash(family.password, salt, null).catch(next);
family.password = hash;
next();
});
- Is this refactoring actually correct?
How can I double check that errors in
bcryptGenSaltorbcryptHashare caught correctly? Is there a way to somehow "force"bcryptGenSaltinto throwing an error, for testing?Next step, how can I remove the two
.catch(next), using awrapAsyncutil function:
wrapAsync.js:
module.exports = fn => (req, res, next) => fn(req, res, next).catch(next);
Following attempt is not working, error: family.isModified() is not a function, (probably because the this is not right anymore).
And what to do with the arguments of wrapAsync, as next should be the 3rd argument?
familySchema.pre(
'save',
wrapAsync(async function(req, res, next) {
var family = this;
const SALT_FACTOR = 14;
debugger;
if (!family.isModified('password')) return next();
const salt = await bcryptGenSalt(SALT_FACTOR);
const hash = await bcryptHash(family.password, salt, null);
family.password = hash;
next();
})
);
express error-handling promise this
add a comment |
up vote
0
down vote
favorite
In an express + passport + local strategy app, I use bcrypt to hash password, this is working:
var bcrypt = require('bcrypt-nodejs');
familySchema.pre('save', function(next) {
var family = this;
var SALT_FACTOR = 14;
if (!family.isModified('password')) return next();
bcrypt.genSalt(SALT_FACTOR, function(err, salt) {
if (err) return next(err);
bcrypt.hash(family.password, salt, null, function(err, hash) {
if (err) return next(err);
family.password = hash;
next();
});
});
});
Then I refactored using promisify and async/await:
const bcrypt = require('bcrypt-nodejs');
const util = require('util');
const bcryptGenSalt = util.promisify(bcrypt.genSalt);
const bcryptHash = util.promisify(bcrypt.hash);
familySchema.pre('save', async function(next) {
var family = this;
const SALT_FACTOR = 14;
if (!family.isModified('password')) return next();
const salt = await bcryptGenSalt(SALT_FACTOR).catch(next);
const hash = await bcryptHash(family.password, salt, null).catch(next);
family.password = hash;
next();
});
- Is this refactoring actually correct?
How can I double check that errors in
bcryptGenSaltorbcryptHashare caught correctly? Is there a way to somehow "force"bcryptGenSaltinto throwing an error, for testing?Next step, how can I remove the two
.catch(next), using awrapAsyncutil function:
wrapAsync.js:
module.exports = fn => (req, res, next) => fn(req, res, next).catch(next);
Following attempt is not working, error: family.isModified() is not a function, (probably because the this is not right anymore).
And what to do with the arguments of wrapAsync, as next should be the 3rd argument?
familySchema.pre(
'save',
wrapAsync(async function(req, res, next) {
var family = this;
const SALT_FACTOR = 14;
debugger;
if (!family.isModified('password')) return next();
const salt = await bcryptGenSalt(SALT_FACTOR);
const hash = await bcryptHash(family.password, salt, null);
family.password = hash;
next();
})
);
express error-handling promise this
I just realized that I'm usingbcrypt-nodejspackage instead of officialbcrypt! And bcrypt support promises. As per bcrypt documentation ( github.com/kelektiv/node.bcrypt.js#with-promises ), bcrypt will automatically output a promise if no callback function is provided. So I can remove thepromisifypart.
– xiaoju
Nov 9 at 9:50
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
In an express + passport + local strategy app, I use bcrypt to hash password, this is working:
var bcrypt = require('bcrypt-nodejs');
familySchema.pre('save', function(next) {
var family = this;
var SALT_FACTOR = 14;
if (!family.isModified('password')) return next();
bcrypt.genSalt(SALT_FACTOR, function(err, salt) {
if (err) return next(err);
bcrypt.hash(family.password, salt, null, function(err, hash) {
if (err) return next(err);
family.password = hash;
next();
});
});
});
Then I refactored using promisify and async/await:
const bcrypt = require('bcrypt-nodejs');
const util = require('util');
const bcryptGenSalt = util.promisify(bcrypt.genSalt);
const bcryptHash = util.promisify(bcrypt.hash);
familySchema.pre('save', async function(next) {
var family = this;
const SALT_FACTOR = 14;
if (!family.isModified('password')) return next();
const salt = await bcryptGenSalt(SALT_FACTOR).catch(next);
const hash = await bcryptHash(family.password, salt, null).catch(next);
family.password = hash;
next();
});
- Is this refactoring actually correct?
How can I double check that errors in
bcryptGenSaltorbcryptHashare caught correctly? Is there a way to somehow "force"bcryptGenSaltinto throwing an error, for testing?Next step, how can I remove the two
.catch(next), using awrapAsyncutil function:
wrapAsync.js:
module.exports = fn => (req, res, next) => fn(req, res, next).catch(next);
Following attempt is not working, error: family.isModified() is not a function, (probably because the this is not right anymore).
And what to do with the arguments of wrapAsync, as next should be the 3rd argument?
familySchema.pre(
'save',
wrapAsync(async function(req, res, next) {
var family = this;
const SALT_FACTOR = 14;
debugger;
if (!family.isModified('password')) return next();
const salt = await bcryptGenSalt(SALT_FACTOR);
const hash = await bcryptHash(family.password, salt, null);
family.password = hash;
next();
})
);
express error-handling promise this
In an express + passport + local strategy app, I use bcrypt to hash password, this is working:
var bcrypt = require('bcrypt-nodejs');
familySchema.pre('save', function(next) {
var family = this;
var SALT_FACTOR = 14;
if (!family.isModified('password')) return next();
bcrypt.genSalt(SALT_FACTOR, function(err, salt) {
if (err) return next(err);
bcrypt.hash(family.password, salt, null, function(err, hash) {
if (err) return next(err);
family.password = hash;
next();
});
});
});
Then I refactored using promisify and async/await:
const bcrypt = require('bcrypt-nodejs');
const util = require('util');
const bcryptGenSalt = util.promisify(bcrypt.genSalt);
const bcryptHash = util.promisify(bcrypt.hash);
familySchema.pre('save', async function(next) {
var family = this;
const SALT_FACTOR = 14;
if (!family.isModified('password')) return next();
const salt = await bcryptGenSalt(SALT_FACTOR).catch(next);
const hash = await bcryptHash(family.password, salt, null).catch(next);
family.password = hash;
next();
});
- Is this refactoring actually correct?
How can I double check that errors in
bcryptGenSaltorbcryptHashare caught correctly? Is there a way to somehow "force"bcryptGenSaltinto throwing an error, for testing?Next step, how can I remove the two
.catch(next), using awrapAsyncutil function:
wrapAsync.js:
module.exports = fn => (req, res, next) => fn(req, res, next).catch(next);
Following attempt is not working, error: family.isModified() is not a function, (probably because the this is not right anymore).
And what to do with the arguments of wrapAsync, as next should be the 3rd argument?
familySchema.pre(
'save',
wrapAsync(async function(req, res, next) {
var family = this;
const SALT_FACTOR = 14;
debugger;
if (!family.isModified('password')) return next();
const salt = await bcryptGenSalt(SALT_FACTOR);
const hash = await bcryptHash(family.password, salt, null);
family.password = hash;
next();
})
);
express error-handling promise this
express error-handling promise this
edited Nov 8 at 14:04
asked Nov 8 at 13:50
xiaoju
526
526
I just realized that I'm usingbcrypt-nodejspackage instead of officialbcrypt! And bcrypt support promises. As per bcrypt documentation ( github.com/kelektiv/node.bcrypt.js#with-promises ), bcrypt will automatically output a promise if no callback function is provided. So I can remove thepromisifypart.
– xiaoju
Nov 9 at 9:50
add a comment |
I just realized that I'm usingbcrypt-nodejspackage instead of officialbcrypt! And bcrypt support promises. As per bcrypt documentation ( github.com/kelektiv/node.bcrypt.js#with-promises ), bcrypt will automatically output a promise if no callback function is provided. So I can remove thepromisifypart.
– xiaoju
Nov 9 at 9:50
I just realized that I'm using
bcrypt-nodejs package instead of official bcrypt! And bcrypt support promises. As per bcrypt documentation ( github.com/kelektiv/node.bcrypt.js#with-promises ), bcrypt will automatically output a promise if no callback function is provided. So I can remove the promisify part.– xiaoju
Nov 9 at 9:50
I just realized that I'm using
bcrypt-nodejs package instead of official bcrypt! And bcrypt support promises. As per bcrypt documentation ( github.com/kelektiv/node.bcrypt.js#with-promises ), bcrypt will automatically output a promise if no callback function is provided. So I can remove the promisify part.– xiaoju
Nov 9 at 9:50
add a comment |
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
The refactoring is not correct, because after the .catch statements, the rest of the function will continue to run. So if for instance bcryptGenSalt throws an error, next is called (because of .catch(next)) but it will also continue with the next line of code, until the end of the function (where next is called again).
Typically, in async functions, you use try/catch around statements that may throw errors:
familySchema.pre('save', async function(next) {
const SALT_FACTOR = 14;
if (!this.isModified('password')) return next();
try {
const salt = await bcryptGenSalt(SALT_FACTOR);
const hash = await bcryptHash(this.password, salt, null);
this.password = hash;
return next();
} catch(err) {
return next(err);
}
});
Is there a way to somehow "force"
bcryptGenSaltinto throwing an error, for testing?
It depends on which tools you use for testing, but there are packages like sinon that can stub existing functions so you can controllably make then throw errors, which you can then test for.
"because after the .catch statements, the rest of the function will continue to run" --> Does this mean that the pattern described in thecodebarbarian.com/80-20-guide-to-express-error-handling should be avoided? In short, they use a wrapAsync() function to automatically add a .catch(next) to async function calls.
– xiaoju
Nov 9 at 14:26
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
The refactoring is not correct, because after the .catch statements, the rest of the function will continue to run. So if for instance bcryptGenSalt throws an error, next is called (because of .catch(next)) but it will also continue with the next line of code, until the end of the function (where next is called again).
Typically, in async functions, you use try/catch around statements that may throw errors:
familySchema.pre('save', async function(next) {
const SALT_FACTOR = 14;
if (!this.isModified('password')) return next();
try {
const salt = await bcryptGenSalt(SALT_FACTOR);
const hash = await bcryptHash(this.password, salt, null);
this.password = hash;
return next();
} catch(err) {
return next(err);
}
});
Is there a way to somehow "force"
bcryptGenSaltinto throwing an error, for testing?
It depends on which tools you use for testing, but there are packages like sinon that can stub existing functions so you can controllably make then throw errors, which you can then test for.
"because after the .catch statements, the rest of the function will continue to run" --> Does this mean that the pattern described in thecodebarbarian.com/80-20-guide-to-express-error-handling should be avoided? In short, they use a wrapAsync() function to automatically add a .catch(next) to async function calls.
– xiaoju
Nov 9 at 14:26
add a comment |
up vote
2
down vote
accepted
The refactoring is not correct, because after the .catch statements, the rest of the function will continue to run. So if for instance bcryptGenSalt throws an error, next is called (because of .catch(next)) but it will also continue with the next line of code, until the end of the function (where next is called again).
Typically, in async functions, you use try/catch around statements that may throw errors:
familySchema.pre('save', async function(next) {
const SALT_FACTOR = 14;
if (!this.isModified('password')) return next();
try {
const salt = await bcryptGenSalt(SALT_FACTOR);
const hash = await bcryptHash(this.password, salt, null);
this.password = hash;
return next();
} catch(err) {
return next(err);
}
});
Is there a way to somehow "force"
bcryptGenSaltinto throwing an error, for testing?
It depends on which tools you use for testing, but there are packages like sinon that can stub existing functions so you can controllably make then throw errors, which you can then test for.
"because after the .catch statements, the rest of the function will continue to run" --> Does this mean that the pattern described in thecodebarbarian.com/80-20-guide-to-express-error-handling should be avoided? In short, they use a wrapAsync() function to automatically add a .catch(next) to async function calls.
– xiaoju
Nov 9 at 14:26
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
The refactoring is not correct, because after the .catch statements, the rest of the function will continue to run. So if for instance bcryptGenSalt throws an error, next is called (because of .catch(next)) but it will also continue with the next line of code, until the end of the function (where next is called again).
Typically, in async functions, you use try/catch around statements that may throw errors:
familySchema.pre('save', async function(next) {
const SALT_FACTOR = 14;
if (!this.isModified('password')) return next();
try {
const salt = await bcryptGenSalt(SALT_FACTOR);
const hash = await bcryptHash(this.password, salt, null);
this.password = hash;
return next();
} catch(err) {
return next(err);
}
});
Is there a way to somehow "force"
bcryptGenSaltinto throwing an error, for testing?
It depends on which tools you use for testing, but there are packages like sinon that can stub existing functions so you can controllably make then throw errors, which you can then test for.
The refactoring is not correct, because after the .catch statements, the rest of the function will continue to run. So if for instance bcryptGenSalt throws an error, next is called (because of .catch(next)) but it will also continue with the next line of code, until the end of the function (where next is called again).
Typically, in async functions, you use try/catch around statements that may throw errors:
familySchema.pre('save', async function(next) {
const SALT_FACTOR = 14;
if (!this.isModified('password')) return next();
try {
const salt = await bcryptGenSalt(SALT_FACTOR);
const hash = await bcryptHash(this.password, salt, null);
this.password = hash;
return next();
} catch(err) {
return next(err);
}
});
Is there a way to somehow "force"
bcryptGenSaltinto throwing an error, for testing?
It depends on which tools you use for testing, but there are packages like sinon that can stub existing functions so you can controllably make then throw errors, which you can then test for.
answered Nov 8 at 14:22
robertklep
133k17231240
133k17231240
"because after the .catch statements, the rest of the function will continue to run" --> Does this mean that the pattern described in thecodebarbarian.com/80-20-guide-to-express-error-handling should be avoided? In short, they use a wrapAsync() function to automatically add a .catch(next) to async function calls.
– xiaoju
Nov 9 at 14:26
add a comment |
"because after the .catch statements, the rest of the function will continue to run" --> Does this mean that the pattern described in thecodebarbarian.com/80-20-guide-to-express-error-handling should be avoided? In short, they use a wrapAsync() function to automatically add a .catch(next) to async function calls.
– xiaoju
Nov 9 at 14:26
"because after the .catch statements, the rest of the function will continue to run" --> Does this mean that the pattern described in thecodebarbarian.com/80-20-guide-to-express-error-handling should be avoided? In short, they use a wrapAsync() function to automatically add a .catch(next) to async function calls.
– xiaoju
Nov 9 at 14:26
"because after the .catch statements, the rest of the function will continue to run" --> Does this mean that the pattern described in thecodebarbarian.com/80-20-guide-to-express-error-handling should be avoided? In short, they use a wrapAsync() function to automatically add a .catch(next) to async function calls.
– xiaoju
Nov 9 at 14:26
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53209106%2frefactor-passport-local-strategy-using-promisy-problem-with-catch%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I just realized that I'm using
bcrypt-nodejspackage instead of officialbcrypt! And bcrypt support promises. As per bcrypt documentation ( github.com/kelektiv/node.bcrypt.js#with-promises ), bcrypt will automatically output a promise if no callback function is provided. So I can remove thepromisifypart.– xiaoju
Nov 9 at 9:50