2023年1月17日 星期二

AdonisJs第五天Middleware

前言

middleware是軟體設計的一種模式,可以用於特定事件的“前置”處理或“後置”處理(參見圖片),在AdonisJs裡面又可以把middleware設定為全域或指定兩種,算是我覺得非常簡單又好用的工具。



全域註冊

在./start/kernel.ts檔案裡面可以見到middleware的註冊,

Server.middleware.register([
() => import('@ioc:Adonis/Core/BodyParser'),
])

在這段程式碼中註冊了全域的middleware:BodyParser,BodyParser的作用為解析controller返回的內容,可以把view或是json或是model直接轉譯為前端應該接收的類型,以昨天的程式碼為例

export default class HellosController {
say() {
return {
say: "hello"
}
}
}

這時如果打api前端就可以拿到{ say: "hello" }的物件,不需要再使用ctx.response.json({ say: "hello" })來回傳,有效減少程式碼的長度及重複度。


指定註冊

正常新增專案的情況下,這時是不會有任何註冊的middleware,沒關係我們一步一步來,先在./start/kernel.ts註冊如下

Server.middleware.registerNamed({
api: () => import('App/Middleware/ApiFormat'),
})

接著手動新增檔案./app/Middleware/ApiFormat.ts,主要我希望只要有註冊該middleware,回傳的內容我希望是我指定的格式,程式碼如下

import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class ApiFormatMiddleware {
public async handle({ response }: HttpContextContract, next: () => Promise<void>) {
    
const start: number = Date.now()
    // 進入主程式前
await next()
// 進入主程式後
const resBody = {
code: [0],
data: response.lazyBody?.[0], // 取得主程式返回的內容
}

resBody['time'] = Date.now() - start + ' ms'
response.send(resBody)
}
}

然後再把route稍微修改一下

import Route from "@ioc:Adonis/Core/Route";

Route.get("/", "HellosController.say").middleware(["api"]);

middleware裡面可以直接塞入字串,或是用陣列註冊多個middleware

這樣就大功告成了。我們再試著打一下昨天的api結果會如下

{"code":[0],"data":{"say":"hello"},"time":"2 ms"}

可以完整輸出我希望輸出的格式還有程式執行的時間


小結

其實middleware也不是AdonisJs特有的功能,有興趣的小夥伴可以再去深究他實現的原理,並更有效的運用在自己生活中,他實踐起來並不困難,但卻能為程式碼帶來大大的便利性,算是我非常喜歡的一個功能。

沒有留言:

張貼留言