在express+passport+本地策略应用程序中,我使用bcrypt
对密码进行哈希,这是有效的:
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();
});
});
});
然后我使用promisify
和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();
});
- 这种重构真的正确吗
如何再次检查
bcryptGenSalt
或bcryptHash
中的错误是否被正确捕获?有没有办法以某种方式"强迫"bcryptGenSalt
抛出错误进行测试?下一步,如何使用
wrapAsync
util函数删除两个.catch(next)
:
wrapAsync.js
:
module.exports = fn => (req, res, next) => fn(req, res, next).catch(next);
以下尝试无效,错误:family.isModified()
不是函数(可能是因为this
不再正确(。如何处理wrapAsync的参数,因为next
应该是第三个参数?
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();
})
);
重构是不正确的,因为在.catch
语句之后,函数的其余部分将继续运行。因此,例如,如果bcryptGenSalt
抛出错误,则会调用next
(因为.catch(next)
(,但它也会继续执行下一行代码,直到函数结束(再次调用next
(。
通常,在async
函数中,使用try/catch
处理可能引发错误的语句:
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);
}
});
有没有办法以某种方式"强迫"
bcryptGenSalt
抛出错误进行测试?
这取决于您使用哪些工具进行测试,但也有像sinon
这样的包可以截断现有函数,这样您就可以可控地制造然后抛出错误,然后进行测试。