钩子和链式调用约定


🌐 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)运行。如果 hook1hook2 都定义了一个 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 默认 resolvehook1.resolvehook2.resolve

🌐 Node.js default resolvehook1.resolvehook2.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.