Fastify 裝飾器

2020-02-06 15:40 更新

裝飾器

想給 Fastify 實(shí)例新增功能?decorate 正是你所需要的 API!

decorate 允許你向 Fastify 實(shí)例添加新的屬性。屬性的值的類型沒有限制,可以是函數(shù)、對(duì)象、字符串等。

使用方法

decorate 你只需調(diào)用 decorate 函數(shù),并將新屬性的名稱與值作為參數(shù)傳遞即可。

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

正如上文所述,你還可以傳遞非函數(shù)的值:

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

一旦添加了一個(gè)裝飾器,你就可以通過其名稱訪問它的值了:

fastify.utility()

console.log(fastify.conf.db)

decorateReply 顧名思義,decorateReply API允許你向 Reply 核心對(duì)象添加新方法。同 decorate 一樣,將新屬性與其值作為參數(shù)傳遞便大功告成了:

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

注:使用箭頭函數(shù)會(huì)破壞 this 和 Fastify Reply 實(shí)例的綁定。

decorateRequest 同理,使用 decorateRequest 可向 Request 核心對(duì)象新增方法。傳遞的參數(shù)同樣也是新屬性的名稱以及值:

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

注:使用箭頭函數(shù)會(huì)破壞 this 和 Fastify Request 實(shí)例的綁定。

裝飾器與封裝

在經(jīng)過封裝的同一個(gè)插件中,如果通過 decorate、decorateRequest 以及 decorateReply 多次定義了一個(gè)同名的的裝飾器,F(xiàn)astify 將會(huì)拋出一個(gè)異常。

下面的示例會(huì)拋出異常:

const server = require('fastify')()
server.decorateReply('view', function (template, args) {
  // 頁(yè)面渲染引擎的代碼。
})
server.get('/', (req, reply) => {
  reply.view('/index.html', { hello: 'world' })
})
// 當(dāng)在其他地方定義
// view 裝飾器時(shí),拋出異常。
server.decorateReply('view', function (template, args) {
  // 另一個(gè)渲染引擎。
})
server.listen(3000)

但下面這個(gè)例子不會(huì)拋異常:

const server = require('fastify')()
  server.decorateReply('view', function (template, args) {
  // 頁(yè)面渲染引擎的代碼。
})
server.register(async function (server, opts) {
  // 我們?cè)诋?dāng)前封裝的插件內(nèi)添加了一個(gè) view 裝飾器。
  // 這么做不會(huì)拋出異常。
  // 因?yàn)椴寮獠亢蛢?nèi)部的 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" 對(duì)象。這些對(duì)象擁有著名為 getter 與 setter 的函數(shù) (盡管 setter 是可選的)。這么做便可以通過裝飾器來定義屬性。例如:

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

上例會(huì)在 Fastify 實(shí)例中定義一個(gè) foo 屬性:

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

Usage Notes

decorateReply 與 decorateRequest 是分別用于向 Reply 和 Request 對(duì)象新增方法或?qū)傩缘摹D憧梢酝ㄟ^對(duì)象直接訪問這些屬性來更新它們。

讓我們向 Request 對(duì)象添加一個(gè)用戶屬性:

// 添加一個(gè) 'user' 請(qǐng)求裝飾器
fastify.decorateRequest('user', '')

// 更新屬性
fastify.addHook('preHandler', (req, reply, done) => {
  req.user = 'Bob Dylan'
  done()
})
// 最后,訪問裝飾器
fastify.get('/', (req, reply) => {
  reply.send(`Hello ${req.user}!`)
})

注:在這個(gè)例子里,使用 decorateReply 或 decorateRequest 不是必要的,但這么做能提升 Fastify 的性能。

同步與異步

decorate 是 同步 的 API。如果你需要添加一個(gè) 異步 引導(dǎo)的裝飾器,F(xiàn)astify 可能會(huì)在該裝飾器準(zhǔn)備妥當(dāng)前啟動(dòng)。為了避免這種情況,你應(yīng)該將 register 與 fastify-plugin 一起使用。更多內(nèi)容,請(qǐng)看插件一文。

依賴項(xiàng)

如果你的裝飾器依賴于其他裝飾器,你可以輕易地將其他裝飾器聲明為依賴項(xiàng)。你要做的只是將一個(gè)字符串?dāng)?shù)組 (表示依賴項(xiàng)的名稱) 作為函數(shù)的第三個(gè)參數(shù)而已:

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

如果依賴關(guān)系不滿足,decorate 會(huì)拋出異常。但請(qǐng)別擔(dān)心:依賴檢查是在服務(wù)器啟動(dòng)之前執(zhí)行的,因此,在運(yùn)行時(shí)不會(huì)發(fā)生該問題。

hasDecorator

使用 hasDecorator API 檢查一個(gè)裝飾器是否存在:

fastify.hasDecorator('utility')

hasRequestDecorator

使用 hasRequestDecorator API 檢查一個(gè)請(qǐng)求的的裝飾器是否存在:

fastify.hasRequestDecorator('utility')

hasReplyDecorator

使用 hasReplyDecorator API 檢查一個(gè)回復(fù)的裝飾器是否存在:

fastify.hasReplyDecorator('utility')


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)