Express 使用promisy重构passport本地策略。.catch()的问题

Express 使用promisy重构passport本地策略。.catch()的问题,express,error-handling,promise,this,Express,Error Handling,Promise,This,在express+passport+local strategy应用程序中,我使用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.

在express+passport+local strategy应用程序中,我使用
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()
不是函数(可能是因为
不再正确)。 以及如何处理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抛出一个错误来进行测试


这取决于您用于测试的工具,但也有类似的包可以存根现有函数,这样您就可以可控地产生然后抛出错误,然后进行测试。

重构是不正确的,因为在
.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抛出一个错误来进行测试


这取决于您用于测试的工具,但也有类似的包可以存根现有函数,这样您就可以可控地产生然后抛出错误,然后进行测试。

我刚刚意识到我使用的是
bcrypt nodejs
包,而不是官方的
bcrypt
!和bcrypt支持承诺。根据bcrypt文档(),如果没有提供回调函数,bcrypt将自动输出一个承诺。因此我可以删除
promisify
部分。我刚刚意识到我使用的是
bcrypt nodejs
包,而不是官方的
bcrypt
!和bcrypt支持承诺。根据bcrypt文档(),如果没有提供回调函数,bcrypt将自动输出一个承诺。因此我可以删除
promisify
部分。“因为在.catch语句之后,函数的其余部分将继续运行”-->这是否意味着应该避免中描述的模式?简而言之,他们使用一个wrapAsync()函数来自动向异步函数调用添加一个.catch(next)。“因为在.catch语句之后,函数的其余部分将继续运行”-->这是否意味着应该避免中描述的模式?简而言之,它们使用wrapAsync()函数自动向异步函数调用添加.catch(next)。