繁体   English   中英

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

[英]How to throw an error from an async mongoose middleware post hook

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

代码示例

以下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并仍返回文档。

在此post init hook方法中,您只会收到一个doc

Document.prototype.init()

参数doc由mongo返回的“对象”文档初始化文档,而不使用设置方法或标记任何已修改的内容。

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

猫鼬文档: Init HookDocumentation

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

发布中间件

挂钩方法及其所有前置中间件完成后,将执行后置中间件。 发布中间件不会直接接收流控制,例如, 不会将下一个或完成的回调传递给它。 post hooks是为这些方法注册传统事件侦听器的一种方法。

猫鼬文档: 后中间件

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

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

      console.log(o);
    });

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

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');
});

错误处理示例: 错误处理

猫鼬维护者在这里。 不幸的是, init()挂钩是同步的,并且我们还没有很好地记录下来。 我们打开了GitHub问题 ,并将尽快添加文档。 报告post('init')的错误的唯一方法是throw错误。

const assert = require('assert');
const mongoose = require('mongoose');
mongoose.set('debug', true);

const GITHUB_ISSUE = `init`;
const connectionString = `mongodb://localhost:27017/${ GITHUB_ISSUE }`;
const { Schema } = mongoose;

run().then(() => console.log('done')).catch(error => console.error(error.stack));

async function run() {
  await mongoose.connect(connectionString);
  await mongoose.connection.dropDatabase();

  const schema = new mongoose.Schema({
    name: String
  });
  schema.post('init', () => { throw new Error('Oops!'); });

  const M = mongoose.model('Test', schema);

  await M.create({ name: 'foo' });

  await M.findOne(); // Throws "Oops!"
}

这是因为Mongoose假定init()在内部是同步的

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM