增加事件监听器

Antora 扩展程序的大部分工作由事件监听器完成。事件监听器是一个函数,每当它监听的事件发生时就会被调用。监听器返回的任何值都将被忽略。注册函数负责将这些监听器函数与特定事件关联起来。为此,它将事件名称和监听函数传递给生成器上下文的 on 方法,即添加监听器。生成器上下文的 API 与 Node.js 的 EventEmitter 相同。

让我们以已定义的扩展为基础,更新它以添加一个事件监听器。我们将监听 playbookBuiltsitePublished 事件,它们是生成器触发的第一个和最后一个事件。这样我们就有机会大致估算生成和发布网站所需的时间。

Example 1. time-generation-extension.js
module.exports.register = function () {
  this
    .on('playbookBuilt', () => {
      console.time('generation time')
    })
    .on('sitePublished', () => {
      console.timeEnd('generation time')
    })
}

Example 1 中,我们使用生成器上下文的 on 方法添加了两个监听器,一个用于在 playbookBuilt 事件触发时监听,另一个用于在 sitePublished 事件触发时监听。on 方法会返回生成器上下文,因此我们可以用它来进行链式调用,如上一示例所示。

由于内置事件只发生一次,因此可以使用 "once" 而不是 "on" 为内置事件注册监听器。

this.once('playbookBuilt', () => { ... })

使用 once 提供了一个非常小的优化。一旦没有剩余的侦听器,事件发射器就会自行停用。

默认情况下,监听器会按照添加的顺序被调用。为了保证我们的计时器在其他扩展的监听器被调用之前启动,我们的 playbookBuilt 监听器应该在 playbookBuilt 事件的其他监听器之前被调用,而我们的 sitePublished 监听器应该在 sitePublished 事件的其他监听器之后被调用。要实现这一点,我们必须做两处改动。

首先,我们可以使用 prependListener 方法代替 on,将 playbookBuilt 监听器添加到已与该事件关联的其他监听器之前。

Example 2. time-generation-extension.js
module.exports.register = function () {
  this
    .prependListener('playbookBuilt', () => {
      console.time('generation time')
    })
    .on('sitePublished', () => {
      console.timeEnd('generation time')
    })
}

其次,我们应该在 playbook 中最后列出我们的扩展。采取这两个步骤可确保我们的定时器绕过所有其他监听器运行。

如果您想为生成器的某个特定阶段计时,可以更新此扩展以监听 其他生成器事件。要将计时器一直扩展到 Node.js 退出时,可以监听 Node.js 进程对象上的 exit 事件。

process.on('exit', () => {
  console.timeEnd('generation time')
})

要了解有关 exit 事件和 Node.js 进程发出的其他事件的更多信息,请参阅 Node.js 进程事件

生成器上下文继承的 EventEmitter API 还允许检索、删除和重新添加监听器。这样,如果有需要,一个扩展就有可能重新安排其他扩展添加的监听器。扩展还可以使用相同的方法发射和监听自定义事件。

要做一些比计时执行和向控制台打印信息更有趣的事情,我们需要 使用上下文变量。接下来,让我们学习一下如何做到这一点。