Fastify 装饰器

2020-02-06 15:40 更新

装饰器

想给 Fastify 实例新增功能?decorate 正是你所需要的 API!

decorate 允许你向 Fastify 实例添加新的属性。属性的值的类型没有限制,可以是函数、对象、字符串等。

使用方法

decorate 你只需调用 decorate 函数,并将新属性的名称与值作为参数传递即可。

fastify.decorate('utility', () => {
  // 新功能的代码
})

正如上文所述,你还可以传递非函数的值:

fastify.decorate('conf', {
  db: 'some.db',
  port: 3000
})

一旦添加了一个装饰器,你就可以通过其名称访问它的值了:

fastify.utility()

console.log(fastify.conf.db)

decorateReply 顾名思义,decorateReply API允许你向 Reply 核心对象添加新方法。同 decorate 一样,将新属性与其值作为参数传递便大功告成了:

fastify.decorateReply('utility', function () {
  // 新功能的代码
})

注:使用箭头函数会破坏 this 和 Fastify Reply 实例的绑定。

decorateRequest 同理,使用 decorateRequest 可向 Request 核心对象新增方法。传递的参数同样也是新属性的名称以及值:

fastify.decorateRequest('utility', function () {
  // 新功能的代码
})

注:使用箭头函数会破坏 this 和 Fastify Request 实例的绑定。

装饰器与封装

在经过封装的同一个插件中,如果通过 decorate、decorateRequest 以及 decorateReply 多次定义了一个同名的的装饰器,Fastify 将会抛出一个异常。

下面的示例会抛出异常:

const server = require('fastify')()
server.decorateReply('view', function (template, args) {
  // 页面渲染引擎的代码。
})
server.get('/', (req, reply) => {
  reply.view('/index.html', { hello: 'world' })
})
// 当在其他地方定义
// view 装饰器时,抛出异常。
server.decorateReply('view', function (template, args) {
  // 另一个渲染引擎。
})
server.listen(3000)

但下面这个例子不会抛异常:

const server = require('fastify')()
  server.decorateReply('view', function (template, args) {
  // 页面渲染引擎的代码。
})
server.register(async function (server, opts) {
  // 我们在当前封装的插件内添加了一个 view 装饰器。
  // 这么做不会抛出异常。
  // 因为插件外部和内部的 view 装饰器是不一样的。
  server.decorateReply('view', function (template, args) {
    // another rendering engine
  })
  server.get('/', (req, reply) => {
    reply.view('/index.page', { hello: 'world' })
  })
}, { prefix: '/bar' })
server.listen(3000)

Getter 和 Setter

装饰器接受特别的 "getter/setter" 对象。这些对象拥有着名为 getter 与 setter 的函数 (尽管 setter 是可选的)。这么做便可以通过装饰器来定义属性。例如:

fastify.decorate('foo', {
  getter () {
    return 'a getter'
  }
})

上例会在 Fastify 实例中定义一个 foo 属性:

console.log(fastify.foo) // 'a getter'

Usage Notes

decorateReply 与 decorateRequest 是分别用于向 Reply 和 Request 对象新增方法或属性的。你可以通过对象直接访问这些属性来更新它们。

让我们向 Request 对象添加一个用户属性:

// 添加一个 'user' 请求装饰器
fastify.decorateRequest('user', '')

// 更新属性
fastify.addHook('preHandler', (req, reply, done) => {
  req.user = 'Bob Dylan'
  done()
})
// 最后,访问装饰器
fastify.get('/', (req, reply) => {
  reply.send(`Hello ${req.user}!`)
})

注:在这个例子里,使用 decorateReply 或 decorateRequest 不是必要的,但这么做能提升 Fastify 的性能。

同步与异步

decorate 是 同步 的 API。如果你需要添加一个 异步 引导的装饰器,Fastify 可能会在该装饰器准备妥当前启动。为了避免这种情况,你应该将 register 与 fastify-plugin 一起使用。更多内容,请看插件一文。

依赖项

如果你的装饰器依赖于其他装饰器,你可以轻易地将其他装饰器声明为依赖项。你要做的只是将一个字符串数组 (表示依赖项的名称) 作为函数的第三个参数而已:

fastify.decorate('utility', fn, ['greet', 'log'])

如果依赖关系不满足,decorate 会抛出异常。但请别担心:依赖检查是在服务器启动之前执行的,因此,在运行时不会发生该问题。

hasDecorator

使用 hasDecorator API 检查一个装饰器是否存在:

fastify.hasDecorator('utility')

hasRequestDecorator

使用 hasRequestDecorator API 检查一个请求的的装饰器是否存在:

fastify.hasRequestDecorator('utility')

hasReplyDecorator

使用 hasReplyDecorator API 检查一个回复的装饰器是否存在:

fastify.hasReplyDecorator('utility')


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号