zoukankan      html  css  js  c++  java
  • mongoose 文档(六) Middleware

    中间件(也称为pre and post hook)是执行异步函数期间传递控制权的函数。中间件在schema级别上被指定并对于编写插件非常有用。Mongoose 4.0有两种中间件:document 中间件和query 中间件。document中间件支持以下document 函数。

     query中间件支持以下model和query函数。

    document中间件和query中间件都支持 pre hooks 和 post hooks。下面详细描述pre hooks 和 post hooks如何工作。

    注意:没有对remove()的query hook,只有对document的。如果你设置了一个remove hook,执行myDoc.remove()时它会激活,而不是执行MyModel.remove()。

    Pre

    有2种类型的pre hook,串行(seria)和并行(parallel)。

    Serial

    串行中间件是一个接一个执行,每个中间件调用next。

    var schema = new Schema(..);
    schema.pre('save', function(next) {
      // 做些什么
      next();
    });

    Parallel

    并行中间件提供更细粒度的操作

    var schema = new Schema(..);
    
    // 'true'表示这是一个并行中间件. 如果你想要使用并行中间件,你必须指定true作为第二个参数 
    schema.pre('save', true, function(next, done) {
      // 下一个要执行的中间件并行执行
      next();
      setTimeout(done, 100);
    });

    在这种情况下,hooked方法直到每个中间件都调用了done才会执行保存。

    用例

    中间件有用于雾化model逻辑和避免异步代码嵌套。这里有一些其他的例子:

    • 复杂验证
    • 删除相关document,如删除用户也删除了他所有的博客文章
    • 异步缺省
    • 某个特定动作触发异步任务,例如触发自定义事件和通知

    错误处理

    如果任何一个中间件调用next或done 处理错误实例,流程会被阻止,并且该错误被传递给回调。

    schema.pre('save', function(next) {
      // You **must** do `new Error()`. `next('something went wrong')` will
      // **not** work
      var err = new Error('something went wrong');
      next(err);
    });
    
    // later...
    
    myDoc.save(function(err) {
      console.log(err.message) // something went wrong
    });

    Post 中间件

    post中间件在hooked方法和所有它的pre中间件完成后才执行。post中间件不直接接收流控制,如没有next和done回调都传递给它。post hook能够为这些方法注册传统的事件监听器。

    schema.post('init', function(doc) {
      console.log('%s has been initialized from the db', doc._id);
    });
    schema.post('validate', function(doc) {
      console.log('%s has been validated (but not saved yet)', doc._id);
    });
    schema.post('save', function(doc) {
      console.log('%s has been saved', doc._id);
    });
    schema.post('remove', function(doc) {
      console.log('%s has been removed', doc._id);
    });

    异步Post hook

    虽然post中间件不接受流控制,你仍然能够确保异步post hook能按预先定义的顺序执行。如果你的post hook方法至少需要2个参数,mongoose会假设第二个参数是你将调用的next()函数来依次触发next中间件

    // Takes 2 parameters: this is an asynchronous post hook
    schema.post('save', function(doc, next) {
      setTimeout(function() {
        console.log('post1');
        // Kick off the second post hook
        next();
      }, 10);
    });
    
    // Will not execute until the first middleware calls `next()`
    schema.post('save', function(doc, next) {
      console.log('post2');
      next();
    });

    Save/Validate Hooks

     save()函数触发validate() hook,因为mongoose 有一个内置的pre('save') hook 执行validate()。这意味着所有pre('validate') 和post('validate') hook在任何pre('save') hook前被调用。

    schema.pre('validate', function() {
      console.log('this gets printed first');
    });
    schema.post('validate', function() {
      console.log('this gets printed second');
    });
    schema.pre('save', function() {
      console.log('this gets printed third');
    });
    schema.post('save', function() {
      console.log('this gets printed fourth');
    });

    Notes on findAndUpdate() 和 Query中间件

    Pre 和 post save() hooks 不在update()、findOneAndUpdate()等执行。 想知道为什么你可以看这个GitHub问题。Mongoose 4.0 对这些函数有清楚的hook。

    schema.pre('find', function() {
      console.log(this instanceof mongoose.Query); // true
      this.start = Date.now();
    });
    
    schema.post('find', function(result) {
      console.log(this instanceof mongoose.Query); // true
      // prints returned documents
      console.log('find() returned ' + JSON.stringify(result));
      // prints number of milliseconds the query took
      console.log('find() took ' + (Date.now() - this.start) + ' millis');
    });

     query中间件与document中间件在一个微秒而重要的地方不同:在document中间件,这是指正在更新的document。在query中间件,mongoose不一定与document更新有关,因此这是指query对象而不是更新document。

    例如,如果你想要增加一个updatedAt时间戳给每个update(),你要使用下面的pre hook。

    schema.pre('update', function() {
      this.update({},{ $set: { updatedAt: new Date() } });
    });
  • 相关阅读:
    Struts2再曝高危漏洞(S2-020补丁绕过)
    JavaWeb学习总结(十三)——使用Session防止表单重复提交
    JavaWeb学习总结(十二)——Session
    javaweb学习总结(十一)——使用Cookie进行会话管理
    如何做个好员工(转载)
    剖析云计算中的“共享型数据库”(转载)
    云计算的基本概念(转载)
    javaweb学习总结(十)——HttpServletRequest对象(一)
    javaweb学习总结(九)—— 通过Servlet生成验证码图片
    javaweb学习总结(八)——HttpServletResponse对象(二)
  • 原文地址:https://www.cnblogs.com/surahe/p/5186813.html
Copyright © 2011-2022 走看看