想給 Fastify 實例新增功能?decorate 正是你所需要的 API!
decorate 允許你向 Fastify 實例添加新的屬性。屬性的值的類型沒有限制,可以是函數(shù)、對象、字符串等。
decorate 你只需調(diào)用 decorate 函數(shù),并將新屬性的名稱與值作為參數(shù)傳遞即可。
fastify.decorate('utility', () => {
// 新功能的代碼
})
正如上文所述,你還可以傳遞非函數(shù)的值:
fastify.decorate('conf', {
db: 'some.db',
port: 3000
})
一旦添加了一個裝飾器,你就可以通過其名稱訪問它的值了:
fastify.utility()
console.log(fastify.conf.db)
decorateReply 顧名思義,decorateReply API允許你向 Reply 核心對象添加新方法。同 decorate 一樣,將新屬性與其值作為參數(shù)傳遞便大功告成了:
fastify.decorateReply('utility', function () {
// 新功能的代碼
})
注:使用箭頭函數(shù)會破壞 this 和 Fastify Reply 實例的綁定。
decorateRequest 同理,使用 decorateRequest 可向 Request 核心對象新增方法。傳遞的參數(shù)同樣也是新屬性的名稱以及值:
fastify.decorateRequest('utility', function () {
// 新功能的代碼
})
注:使用箭頭函數(shù)會破壞 this 和 Fastify Request 實例的綁定。
在經(jīng)過封裝的同一個插件中,如果通過 decorate、decorateRequest 以及 decorateReply 多次定義了一個同名的的裝飾器,F(xiàn)astify 將會拋出一個異常。
下面的示例會拋出異常:
const server = require('fastify')()
server.decorateReply('view', function (template, args) {
// 頁面渲染引擎的代碼。
})
server.get('/', (req, reply) => {
reply.view('/index.html', { hello: 'world' })
})
// 當(dāng)在其他地方定義
// 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) {
// 我們在當(dāng)前封裝的插件內(nèi)添加了一個 view 裝飾器。
// 這么做不會拋出異常。
// 因為插件外部和內(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 的函數(shù) (盡管 setter 是可選的)。這么做便可以通過裝飾器來定義屬性。例如:
fastify.decorate('foo', {
getter () {
return 'a getter'
}
})
上例會在 Fastify 實例中定義一個 foo 屬性:
console.log(fastify.foo) // 'a getter'
decorateReply 與 decorateRequest 是分別用于向 Reply 和 Request 對象新增方法或?qū)傩缘?。你可以通過對象直接訪問這些屬性來更新它們。
讓我們向 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。如果你需要添加一個 異步 引導(dǎo)的裝飾器,F(xiàn)astify 可能會在該裝飾器準(zhǔn)備妥當(dāng)前啟動。為了避免這種情況,你應(yīng)該將 register 與 fastify-plugin 一起使用。更多內(nèi)容,請看插件一文。
如果你的裝飾器依賴于其他裝飾器,你可以輕易地將其他裝飾器聲明為依賴項。你要做的只是將一個字符串?dāng)?shù)組 (表示依賴項的名稱) 作為函數(shù)的第三個參數(shù)而已:
fastify.decorate('utility', fn, ['greet', 'log'])
如果依賴關(guān)系不滿足,decorate 會拋出異常。但請別擔(dān)心:依賴檢查是在服務(wù)器啟動之前執(zhí)行的,因此,在運行時不會發(fā)生該問題。
使用 hasDecorator API 檢查一個裝飾器是否存在:
fastify.hasDecorator('utility')
使用 hasRequestDecorator API 檢查一個請求的的裝飾器是否存在:
fastify.hasRequestDecorator('utility')
使用 hasReplyDecorator API 檢查一個回復(fù)的裝飾器是否存在:
fastify.hasReplyDecorator('utility')
更多建議: