<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
中介軟體(Middleware ),特指業務流程的中間處理環節
在處理汙水的時候,一般都要經過三個處理環節,從而保證處理過後的廢水,達到排放標準
處理汙水的這三個中間處理環節,就可以叫做中介軟體。
當一個請求到達 Express 的伺服器之後,可以連續呼叫多箇中介軟體,從而對這次請求進行預處理。
Express 的中介軟體,本質上就是一個 function 處理常式,Express 中介軟體的格式如下:
注意:中介軟體函數的形參列表中,必須包含 next 引數。而路由處理常式中只包含 req 和 res。
next 函數是實現多箇中介軟體連續呼叫的關鍵,它表示把流轉關係轉交給下一個中介軟體或路由。
可以通過如下的方式,定義一個最簡單的中介軟體函數:
使用者端發起的任何請求,到達伺服器之後,都會觸發的中介軟體,叫做全域性生效的中介軟體。
通過呼叫 app.use(中介軟體函數),即可定義一個全域性生效的中介軟體,範例程式碼如下:
const express = require('express') const app = express() // // 定義一個最簡單的中介軟體函數 // const mw = function (req, res, next) { // console.log('這是最簡單的中介軟體函數') // // 把流轉關係,轉交給下一個中介軟體或路由 // next() // } // // 將 mw 註冊為全域性生效的中介軟體 // app.use(mw) // 這是定義全域性中介軟體的簡化形式 app.use((req, res, next) => { console.log('這是最簡單的中介軟體函數') next() }) app.get('/', (req, res) => { console.log('呼叫了 / 這個路由') res.send('Home page.') }) app.get('/user', (req, res) => { console.log('呼叫了 /user 這個路由') res.send('User page.') }) app.listen(80, () => { console.log('http://127.0.0.1') })
當在apifox請求這兩個請求時,都會先呼叫這個中介軟體再返回請求的內容。
多箇中介軟體之間,共用同一份 req 和 res。基於這樣的特性,我們可以在上游的中介軟體中,統一為 req 或 res 物件新增自定義的屬性或方法,供下游的中介軟體或路由進行使用。
const express = require('express') const app = express() // 這是定義全域性中介軟體的簡化形式 app.use((req, res, next) => { // 獲取到請求到達伺服器的時間 const time = Date.now() // 為 req 物件,掛載自定義屬性,從而把時間共用給後面的所有路由 req.startTime = time next() }) app.get('/', (req, res) => { res.send('Home page.' + req.startTime) }) app.get('/user', (req, res) => { res.send('User page.' + req.startTime) }) app.listen(80, () => { console.log('http://127.0.0.1') })
可以使用 app.use() 連續定義多個全域性中介軟體。使用者端請求到達伺服器之後,會按照中介軟體定義的先後順序依次進行呼叫,範例程式碼如下:
const express = require('express') const app = express() // 定義第一個全域性中介軟體 app.use((req, res, next) => { console.log('呼叫了第1個全域性中介軟體') next() }) // 定義第二個全域性中介軟體 app.use((req, res, next) => { console.log('呼叫了第2個全域性中介軟體') next() }) // 定義一個路由 app.get('/user', (req, res) => { res.send('User page.') }) app.listen(80, () => { console.log('http://127.0.0.1') })
不使用 app.use() 定義的中介軟體,叫做區域性生效的中介軟體,範例程式碼如下:
// 匯入 express 模組 const express = require('express') // 建立 express 的伺服器範例 const app = express() // 1. 定義中介軟體函數 const mw1 = (req, res, next) => { console.log('呼叫了區域性生效的中介軟體') next() } // 2. 建立路由,mw1只在當前路由生效 app.get('/', mw1, (req, res) => { res.send('Home page.') }) app.get('/user', (req, res) => { res.send('User page.') }) // 呼叫 app.listen 方法,指定埠號並啟動web伺服器 app.listen(80, function () { console.log('Express server running at http://127.0.0.1') })
可以在路由中,通過如下兩種等價的方式,使用多個區域性中介軟體:
// 匯入 express 模組 const express = require('express') // 建立 express 的伺服器範例 const app = express() // 1. 定義中介軟體函數 const mw1 = (req, res, next) => { console.log('呼叫了第一個區域性生效的中介軟體') next() } const mw2 = (req, res, next) => { console.log('呼叫了第二個區域性生效的中介軟體') next() } // 2. 建立路由 app.get('/', [mw1, mw2], (req, res) => { res.send('Home page.') }) app.get('/user', (req, res) => { res.send('User page.') }) // 呼叫 app.listen 方法,指定埠號並啟動web伺服器 app.listen(80, function () { console.log('Express server running at http://127.0.0.1') })
① 一定要在路由之前註冊中介軟體
② 使用者端傳送過來的請求,可以連續呼叫多箇中介軟體進行處理
③ 執行完中介軟體的業務程式碼之後,不要忘記呼叫 next() 函數
④ 為了防止程式碼邏輯混亂,呼叫 next() 函數後不要再寫額外的程式碼
⑤ 連續呼叫多箇中介軟體時,多箇中介軟體之間,共用 req 和 res 物件
為了方便大家理解和記憶中介軟體的使用,Express 官方把常見的中介軟體用法,分成了 5 大類,分別是:
① 應用級別的中介軟體
② 路由級別的中介軟體
③ 錯誤級別的中介軟體
④ Express 內建的中介軟體
⑤ 第三方的中介軟體
通過 app.use() 或 app.get() 或 app.post() ,繫結到 app 範例上的中介軟體,叫做應用級別的中介軟體,程式碼範例如下:
繫結到 express.Router() 範例上的中介軟體,叫做路由級別的中介軟體。它的用法和應用級別中介軟體沒有任何區別。只不過,應用級別中介軟體是繫結到 app 範例上,路由級別中介軟體系結到 router 範例上,程式碼範例如下:
錯誤級別中介軟體的作用:專門用來捕獲整個專案中發生的異常錯誤,從而防止專案異常崩潰的問題。
格式:錯誤級別中介軟體的 function 處理常式中,必須有 4 個形參,形參順序從前到後,分別是 (err, req, res, next)。
注意:錯誤級別的中介軟體,必須註冊在所有路由之後!
// 匯入 express 模組 const express = require('express') // 建立 express 的伺服器範例 const app = express() // 1. 定義路由 app.get('/', (req, res) => { // 1.1 人為的製造錯誤 throw new Error('伺服器內部發生了錯誤!') res.send('Home page.') }) // 2. 定義錯誤級別的中介軟體,捕獲整個專案的異常錯誤,從而防止程式的崩潰 app.use((err, req, res, next) => { console.log('發生了錯誤!' + err.message) res.send('Error:' + err.message) }) // 呼叫 app.listen 方法,指定埠號並啟動web伺服器 app.listen(80, function () { console.log('Express server running at http://127.0.0.1') })
自 Express 4.16.0 版本開始,Express 內建了 3 個常用的中介軟體,極大的提高了 Express 專案的開發效率和體驗:
① express.static 快速託管靜態資源的內建中介軟體,例如: HTML 檔案、圖片、CSS 樣式等(無相容性)
② express.json 解析 JSON 格式的請求體資料(有相容性,僅在 4.16.0+ 版本中可用)
③ express.urlencoded 解析 URL-encoded 格式的請求體資料(有相容性,僅在 4.16.0+ 版本中可用)
// 匯入 express 模組 const express = require('express') // 建立 express 的伺服器範例 const app = express() // 注意:除了錯誤級別的中介軟體,其他的中介軟體,必須在路由之前進行設定 // 通過 express.json() 這個中介軟體,解析表單中的 JSON 格式的資料 app.use(express.json()) // 通過 express.urlencoded() 這個中介軟體,來解析 表單中的 url-encoded 格式的資料 app.use(express.urlencoded({ extended: false })) app.post('/user', (req, res) => { // 在伺服器,可以使用 req.body 這個屬性,來接收使用者端傳送過來的請求體資料 // 預設情況下,如果不設定解析表單資料的中介軟體,則 req.body 預設等於 undefined console.log(req.body) res.send('ok') }) app.post('/book', (req, res) => { // 在伺服器端,可以通過 req,body 來獲取 JSON 格式的表單資料和 url-encoded 格式的資料 console.log(req.body) res.send('ok') }) // 呼叫 app.listen 方法,指定埠號並啟動web伺服器 app.listen(80, function () { console.log('Express server running at http://127.0.0.1') })
非 Express 官方內建的,而是由第三方開發出來的中介軟體,叫做第三方中介軟體。在專案中,大家可以按需下載並設定
第三方中介軟體,從而提高專案的開發效率。
例如:在 express@4.16.0 之前的版本中,經常使用 body-parser 這個第三方中介軟體,來解析請求體資料。使用步
驟如下:
① 執行 npm install body-parser 安裝中介軟體
② 使用 require 匯入中介軟體
③ 呼叫 app.use() 註冊並使用中介軟體
注意:Express 內建的 express.urlencoded 中介軟體,就是基於 body-parser 這個第三方中介軟體進一步封裝出來的。
// 匯入 express 模組 const express = require('express') // 建立 express 的伺服器範例 const app = express() // 1. 匯入解析表單資料的中介軟體 body-parser const parser = require('body-parser') // 2. 使用 app.use() 註冊中介軟體 app.use(parser.urlencoded({ extended: false })) // app.use(express.urlencoded({ extended: false })) app.post('/user', (req, res) => { // 如果沒有設定任何解析表單資料的中介軟體,則 req.body 預設等於 undefined console.log(req.body) res.send('ok') }) // 呼叫 app.listen 方法,指定埠號並啟動web伺服器 app.listen(80, function () { console.log('Express server running at http://127.0.0.1') })
自己手動模擬一個類似於 express.urlencoded 這樣的中介軟體,來解析 POST 提交到伺服器的表單資料。
實現步驟:
① 定義中介軟體
② 監聽 req 的 data 事件
③ 監聽 req 的 end 事件
④ 使用 querystring 模組解析請求體資料
⑤ 將解析出來的資料物件掛載為 req.body
⑥ 將自定義中介軟體封裝為模組
使用 app.use() 來定義全域性生效的中介軟體,程式碼如下:
在中介軟體中,需要監聽 req 物件的 data 事件,來獲取使用者端傳送到伺服器的資料。
如果資料量比較大,無法一次性傳送完畢,則使用者端會把資料切割後,分批傳送到伺服器。所以 data 事件可能會觸發多次,每一次觸發 data 事件時,獲取到資料只是完整資料的一部分,需要手動對接收到的資料進行拼接。
當請求體資料接收完畢之後,會自動觸發 req 的 end 事件。
因此,我們可以在 req 的 end 事件中,拿到並處理完整的請求體資料。範例程式碼如下:
Node.js 內建了一個Qs 模組,專門用來處理查詢字串。通過這個模組提供的 parse() 函數,可以輕鬆把查詢字串,解析成物件的格式。範例程式碼如下:
上游的中介軟體和下游的中介軟體及路由之間,共用同一份 req 和 res。因此,我們可以將解析出來的資料,掛載為 req 的自定義屬性,命名為 req.body,供下游使用。範例程式碼如下:
為了優化程式碼的結構,我們可以把自定義的中介軟體函數,封裝為獨立的模組,範例程式碼如下:
// 匯入 express 模組 const express = require('express') // 建立 express 的伺服器範例 const app = express() // 匯入 Node.js 內建的 Qs 模組 const qs = require('Qs') // 這是解析表單資料的中介軟體 app.use((req, res, next) => { // 定義中介軟體具體的業務邏輯 // 1. 定義一個 str 字串,專門用來儲存使用者端傳送過來的請求體資料 let str = '' // 2. 監聽 req 的 data 事件 req.on('data', (chunk) => { str += chunk }) // 3. 監聽 req 的 end 事件 req.on('end', () => { // 在 str 中存放的是完整的請求體資料 // console.log(str) // TODO: 把字串格式的請求體資料,解析成物件格式 const body = qs.parse(str) req.body = body next() }) }) app.post('/user', (req, res) => { res.send(req.body) }) // 呼叫 app.listen 方法,指定埠號並啟動web伺服器 app.listen(80, function () { console.log('Express server running at http://127.0.0.1') })
// 匯入 Node.js 內建的 Qs 模組 const qs = require('Qs') const bodyParser = (req, res, next) => { // 定義中介軟體具體的業務邏輯 // 1. 定義一個 str 字串,專門用來儲存使用者端傳送過來的請求體資料 let str = '' // 2. 監聽 req 的 data 事件 req.on('data', (chunk) => { str += chunk }) // 3. 監聽 req 的 end 事件 req.on('end', () => { // 在 str 中存放的是完整的請求體資料 // console.log(str) // TODO: 把字串格式的請求體資料,解析成物件格式 const body = qs.parse(str) req.body = body next() }) } module.exports = bodyParser
// 匯入 express 模組 const express = require('express') // 建立 express 的伺服器範例 const app = express() // 1. 匯入自己封裝的中介軟體模組 const customBodyParser = require('./14.custom-body-parser') // 2. 將自定義的中介軟體函數,註冊為全域性可用的中介軟體 app.use(customBodyParser) app.post('/user', (req, res) => { res.send(req.body) }) // 呼叫 app.listen 方法,指定埠號並啟動web伺服器 app.listen(80, function () { console.log('Express server running at http://127.0.0.1') })
到此這篇關於NodeJs Express中介軟體超詳細講解的文章就介紹到這了,更多相關NodeJs Express中介軟體內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45