如何从异步猫鼬中间件后钩引发错误

时间:2018-07-19 13:51:21

标签: javascript node.js mongodb typescript mongoose

从异步Mongoose middleware 发布挂钩引发错误的正确方法是什么?

代码示例

以下 TypeScript 代码使用mongoose的post init事件来运行一些检查,这些检查在函数从mongoDb中检索文档时触发。本示例中的postInit()函数正在执行一些后台检查。在某些情况下应该会失败,然后返回Promise.reject('Error!');

schema.post('init', function (this: Query<any>, doc: any) {
    return instance.postInit(this, doc) 
    .catch( err => {
        return err;
    });
});

该钩子工作正常。即以下代码触发了该钩子:

MyMongooseModel.findOne({ _id : doc.id}, (err, o : any) => {
    console.log(o);
});

但是,如果postInit()失败,则该错误不会传递回调用函数。而是返回文档。

预期行为

我正在寻找正确的方法将此错误传递给调用函数。如果后台检查失败,则调用函数不应收回文档。

我尝试了多种方法来引发此错误。例如。 throw new Error('Error');。但是,这将导致UnhandledPromiseRejectionWarning并仍返回文档。

2 个答案:

答案 0 :(得分:1)

在此 post init钩子方法中,您只会收到 doc

Document.prototype.init()

  

返回的参数doc«Object»文档   mongo初始化文档,不使用setter或进行任何标记   修改。

     

从mongodb返回文档后在内部调用。

猫鼬文档:Init HookDocumentation

要触发错误,您需要完成或下一个方法:

发布中间件

  

post中间件在钩子方法及其所有方法之后执行   中间件预完成。发布中间件不会不直接接收   流量控制,例如没有下一步或完成回调将传递给它。发布   钩子是注册这些事件监听器的一种方法   方法。

猫鼬文档:Post Middleware

如果您只想知道呼叫中是否发生错误,请对此进行更改:

MyMongooseModel.findOne({ _id : doc.id}, (err, o : any) => {
      if(err) {
        throw new Error(err);
      }

      console.log(o);
    });

如果您要传播错误,则一个选项是使用 pre 挂钩方法:

schema.pre('save', function(next) {
  const err = new Error('something went wrong');
  // If you call `next()` with an argument, that argument is assumed to be
  // an error.
  next(err);
});

schema.pre('save', function() {
  // You can also return a promise that rejects
  return new Promise((resolve, reject) => {
    reject(new Error('something went wrong'));
  });
});

schema.pre('save', function() {
  // You can also throw a synchronous error
  throw new Error('something went wrong');
});

schema.pre('save', async function() {
  await Promise.resolve();
  // You can also throw an error in an `async` function
  throw new Error('something went wrong');
});

错误处理示例:Error Handling

答案 1 :(得分:1)

这里的猫鼬维护者。不幸的是,StackPanel.BindingContext钩子是同步的,我们在记录该钩子方面还做得不好。我们打开了GitHub issue,并将尽快添加文档。报告init()中的错误的唯一方法是post('init')

throw

这是因为猫鼬承担init() is synchronous internally