Mongoose 是一个用于 Node.js 的 MongoDB 模型库和对象文档映射 (ODM) 库。在 Mongoose 中,开发者可以使用中间件来处理文章操作的过程,包括在创建、更新、删除文章时执行一些前置或后置逻辑。中间件在 Mongoose 中使用非常普遍,但是中间件的执行顺序却经常会带来很多问题,本文将详细介绍 Mongoose 中间件的执行顺序。
Mongoose 中间件的类型
在 Mongoose 中,中间件主要有以下几种类型:
- 钩子函数 (hook): 在执行 CRUD 操作前,会自动执行的函数,可以用于做一些前置处理,如校验、转换数据等。
- 聚合中间件 (aggregate middleware): 应用于 Model.aggregate() 方法的中间件。
- 查询中间件 (query middleware): 应用于 Model.find()、Model.findOne() 等方法的中间件,用于对查询条件和结果进行处理和转换。
- 文档中间件 (document middleware): 应用于文档对象的中间件,包括在保存、修改、验证等操作前自动执行的函数。
- 模型中间件 (model middleware): 应用于模型的中间件,包括在创建模型、更新模型信息等操作前自动执行的函数。
Mongoose 中间件的执行顺序
Mongoose 中间件的执行顺序与它们的类型有关,在执行 CRUD 操作时,默认的钩子函数执行顺序如下:
- 全局钩子函数,这是执行 CRUD 操作前 Mongoose 默认调用的中间件,无论何时都会在执行操作前运行。
- 针对具体 Model 定义的中间件。
- 针对具体 Query 对象实例定义的中间件。
全局钩子函数
全局钩子函数是在每个 Model 上应用的钩子函数,应用所有操作之前调用。因此,全局钩子函数在 Mongoose 中间件执行顺序中是最优先执行的。可以通过以下代码来添加全局钩子函数:
const mongoose = require('mongoose'); mongoose.plugin((schema) => { schema.pre('save', function(next) { // do something next(); }) });
Model 钩子函数
Model 钩子函数是在每个 Model 上应用的钩子函数,在执行任何与操作一起调用之前调用。 在 Model 钩子函数之前,如果有全局钩子函数,则会首先调用全局钩子函数。可以通过以下代码来添加 Model 钩子函数:
-- -------------------- ---- ------- ----- -------- - -------------------- ----- ---------- - --- ----------------- ------ ------- -------- ------ --- ---------------------- -------------- - -- -- --------- ------- ---
Query 钩子函数
在默认情况下,Query 中间件将被应用于查询实例和文档实例查询的所有操作。Query 钩子将在文档钩子和模型钩子之后调用。可以通过以下代码来添加 Query 钩子函数:
const mongoose = require('mongoose'); const Blog = mongoose.model('Blog', blogSchema); Blog.find().pre('findOne', function() { // do something });
聚合中间件、文档中间件和模型中间件
聚合中间件、文档中间件和模型中间件在 Mongoose 中间件执行顺序中都是最后执行的。可以通过以下代码来添加聚合中间件、文档中间件和模型中间件:
-- -------------------- ---- ------- ----- -------- - -------------------- ----- ---------- - --- ----------------- ------ ------- -------- ------ --- ----------------------- ------------- - -- -- --------- --- ----- ---- - ---------------------- ------------ ------------ ------------- ------- - -- -- --------- --- ----- ---- - --- ------ ------ ------- -------- -------- ----- -- - ---- ----- --- ----------------------- - -- -- --------- ---
示例代码
下面是一个示例代码,演示 Mongoose 中间件的执行顺序:
-- -------------------- ---- ------- ----- -------- - -------------------- --------------------------------------------- ----- ---------- - --- ----------------- ------ ------- -------- ------ --- -- ------ ---------------------- -- - ------------------ -------------- - --------------- ------ --- ------- ------- --- --- -- ----- ---- ---------------------- -------------- - --------------- ----- --- ------- ------- --- -- ----- ---- ----- ---- - ---------------------- ------------ -------------------------- ---------- - --------------- ----- --- ---------- --- -- ----------------- ----------------------- ------------- - --------------- -------- ---- ------- --- ----- ---- - --- ------ ------ ------- -------- -------- ----- -- - ---- ----- --- ----------------------- - ----------------- --------- ---
输出结果:
1. Document Post Save 2. Query Pre FindOne 3. Model Pre Save 4. Global Pre Save Blog saved!
可以看到,聚合中间件、文档中间件和模型中间件最后执行,即使它们的顺序在前面定义。这是因为在执行 CRUD 操作时,实际上是依次调用 Query 钩子、Model 钩子和全局钩子,最后才会执行具体的操作。
总结
Mongoose 中间件的执行顺序是非常重要的,了解了中间件的执行顺序,可以更好地理解 Mongoose 的工作原理,并在实际开发中避免一些问题的发生。在实际使用中,应尽量避免同时使用多种中间件类型,以免影响 Mongoose 中间件的执行顺序。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/654792237d4982a6eb1e9ff5