使用promise重构护照本地策略..catch()有问题



在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();
});
});
});

然后我使用promisifyasync/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();
});
  • 这种重构真的正确吗
  • 如何再次检查bcryptGenSaltbcryptHash中的错误是否被正确捕获?有没有办法以某种方式"强迫"bcryptGenSalt抛出错误进行测试?

  • 下一步,如何使用wrapAsyncutil函数删除两个.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这样的包可以截断现有函数,这样您就可以可控地制造然后抛出错误,然后进行测试。

最新更新