钩子和链式调用约定
🌐 Convention of hooks and chaining
钩子是链的一部分,即使该链只包含一个自定义(用户提供的)钩子和始终存在的默认钩子。
🌐 Hooks are part of a chain, even if that chain consists of only one custom (user-provided) hook and the default hook, which is always present.
Hook 函数可以嵌套:每个函数必须始终返回一个普通对象,链式调用的结果是每个函数调用 next<hookName>(),它是对后续加载器的 hook(按后进先出顺序)的引用。
可以多次调用 registerHooks():
🌐 It's possible to call registerHooks() more than once:
// entrypoint.mjs
import { registerHooks } from 'node:module';
const hook1 = { /* implementation of hooks */ };
const hook2 = { /* implementation of hooks */ };
// hook2 runs before hook1.
registerHooks(hook1);
registerHooks(hook2);// entrypoint.cjs
const { registerHooks } = require('node:module');
const hook1 = { /* implementation of hooks */ };
const hook2 = { /* implementation of hooks */ };
// hook2 runs before hook1.
registerHooks(hook1);
registerHooks(hook2);在本例中,已注册的钩子将形成链。这些链按后进先出(LIFO)运行。如果 hook1 和 hook2 都定义了一个 resolve 钩子,它们将按如下方式被调用(注意从右到左,先从 hook2.resolve,然后 hook1.resolve,最后是 Node.js 默认):
🌐 In this example, the registered hooks will form chains. These chains run
last-in, first-out (LIFO). If both hook1 and hook2 define a resolve
hook, they will be called like so (note the right-to-left,
starting with hook2.resolve, then hook1.resolve, then the Node.js default):
Node.js 默认 resolve ← hook1.resolve ← hook2.resolve
🌐 Node.js default resolve ← hook1.resolve ← hook2.resolve
这同样适用于所有其他钩子。
🌐 The same applies to all the other hooks.
返回缺少必需属性的值的钩子会触发异常。一个钩子如果没有调用 next<hookName>() 并且也没有返回 shortCircuit: true,同样会触发异常。这些错误是为了帮助防止链条意外中断。从钩子返回 shortCircuit: true 表示链条在你的钩子处故意结束。
如果在加载其他钩子模块时应该应用钩子,则其他钩子模块应在钩子注册之后加载。
🌐 If a hook should be applied when loading other hook modules, the other hook modules should be loaded after the hook is registered.