可能是全網最詳細的express--middleware

pubdreamcc發表於2019-05-25

寫在前面

hello,小夥伴們,我是你們的pubdreamcc,本篇博文出至於我的GitHub倉庫node學習教程資料,歡迎小夥伴們點贊和star,你們的點贊是我持續更新的動力。

GitHub倉庫地址:node學習教程

好了,廢話不多說了,今天繼續我們express的學習~

開篇

今天我們來聊一聊express中非常重要的一個概念——express middleware (express中介軟體)。中介軟體實質就是一個函式,我們從傳送一個請求到最後服務端給迴響應,在這個過程中請求會經過多箇中介軟體處理。下面給出一張圖來理解express中介軟體的概念:

可能是全網最詳細的express--middleware

這個是我們平常自來水的處理過程圖,可以看到我們自來水從水庫取出來到最後進入每個家庭,中間經過了多次的處理,我們可以理解為中間的每一個處理過程(方法)稱之為中介軟體。expressmiddleware類似於上圖中的每一個處理過程,我們請求到響應之間也是經過了一個或多箇中介軟體處理,最後才是我們看到的響應結果。

中介軟體的分類和使用

這裡我們可以看下express官網對中介軟體的分類介紹。

express-middleware

  1. Application-level middleware(應用程式級別中介軟體)

應用程式級別中介軟體又分為以下三種情況。

  • 不管請求地址和請求方法,任何請求都能進入。
const app = express()

app.use((req, res, next) => {
  console.log('請求來了1~')
  next()  // 呼叫next(),請求會去下一個緊挨著的匹配的中介軟體
})

app.use((req, res, next) => {
  console.log('請求來了2~')
   // 沒有呼叫next(),請求會留在該中介軟體中
})

app.use((req, res, next) => {
  console.log('請求來了3~')
})

這裡配置了三個應用程式級別的中介軟體,當客戶端發一個請求,就會從上至下首先進入第一個中介軟體處理,接著看是否內部呼叫next()來決定請求是否往下執行。

我們在服務端請求處理函式中還可以傳入第三個引數:next,如果在函式體中呼叫next(),則請求會在經過該中介軟體處理後繼續向下找最近的那個匹配成功的中介軟體,並且進入該中介軟體處理。如果沒有呼叫next(),則請求會留在該中介軟體中,不會繼續往下執行。

結果:

// 請求來了1

// 請求來了2
  • 特定請求路徑的任何型別請求都能進入
const app = express()

app.use('/a', (req, res, next) => {
  console.log('請求來了1~')
  next()  // 呼叫next(),請求會去下一個緊挨著的匹配的中介軟體
})

app.use('/b', (req, res, next) => {
  console.log('請求來了2~')
})

app.use('/a', (req, res, next) => {
  console.log('請求來了3~')
})

同樣的,這裡也配置了三個中介軟體,因為在中介軟體中規定了請求路徑,所以只能是以 /a 開頭 的請求才能進入第一個中介軟體處理。因為在第一個中介軟體內部呼叫了next()方法,所以請求會繼續往下找匹配的中介軟體,第二個中間請求地址不匹配,所以進入第三個中介軟體處理。

結果:

// 請求來了1

// 請求來了3
  • 特定請求方法和特定請求地址的請求能夠進入

對於這種情況我們最為熟悉,之前已經練習過多次。

const app = express()

app.get('/a', (req, res, next) => {
  console.log('請求來了1~')
  next()  // 呼叫next(),請求會去下一個緊挨著的匹配的中介軟體
})

app.post('/a', (req, res, next) => {
  console.log('請求來了2~')
})

app.get('/a', (req, res, next) => {
  console.log('請求來了3~')
})

同樣以上面的例子,寫三個中介軟體。這裡規定了必須以 GET 請求而且請求路徑為:/a的請求會被第一個中介軟體處理,因為內部呼叫了 next(),所以請求會繼續往下找臨近的匹配的中介軟體,第二個中介軟體規定的請求方法為:POST,所以進入第三個中介軟體處理。

結果:

// 請求來了1

// 請求來了3
  1. Router-level middleware(路由級別中介軟體)

路由級別的中介軟體與上面應用程式級別中介軟體的工作方式類似,只不過把路由模組單獨提取出來,最後通過把路由容器掛載到 app 伺服器例項上即可。

  • 不管請求地址和請求方法,任何請求都能進入。
const router = express.Router()

router.use((req, res, next) => {
  console.log('請求來了1~')
  next() // 呼叫next(),請求會去下一個緊挨著的匹配的中介軟體
})

router.use((req, res, next) => {
  console.log('請求來了2~')
  // 沒有呼叫next(),請求停留在此,不會繼續往下找了
})

router.use((req, res, next) => {
  console.log('請求來了3~')
})

結果:

// 請求來了1~

// 請求來了2~
  • 特定請求路徑的任何型別請求都能進入
const router = express.Router()

router.use('/a', (req, res, next) => {
  console.log('請求來了1~')
  next()  // 呼叫next(),請求會去下一個緊挨著的匹配的中介軟體
})

router.use('/b', (req, res, next) => {
  console.log('請求來了2~')
})

router.use('/a', (req, res, next) => {
  console.log('請求來了3~')
})

結果:

// 請求來了1~

// 請求來了3~
  • 特定請求方法和特定請求地址的請求能夠進入
const router = express.Router()

router.get('/a', (req, res, next) => {
  console.log('請求來了1~')
  next()  // 呼叫next(),請求會去下一個緊挨著的匹配的中介軟體
})

router.post('/a', (req, res, next) => {
  console.log('請求來了2~')
})

router.get('/a', (req, res, next) => {
  console.log('請求來了3~')
})

結果:

// 請求來了1~

// 請求來了3~
  1. Error-handling middleware(全域性錯誤處理中介軟體)

在實際開發中,往往我們需要統一來處理非同步操作發生的錯誤,這個時候我們需要在專案中配置一個全域性錯誤處理中介軟體即可。

const express = require('express')

const fs = require('fs')

const app = express()

app.get('/', (req, res, next) => {
  fs.readFile('./index.html', (err, date) => {
    if (err) {
      // 如果非同步讀取檔案錯誤,把錯誤物件傳給next()
      return next(err)
    }
    // 成功,傳送讀取後的資料,瀏覽器渲染頁面
    res.send(data)
  })
})

// 配置一個全域性錯誤處理中介軟體,注意這裡接收四個引數,一個都不能少,否則會出錯

app.use((err, req, res, next) => {
  // err引數為前面next()方法接收到的錯誤物件
  res.status(500).send(err.message)
})

通過配置一個全域性錯誤處理中介軟體,我們可以統一處理請求傳送錯誤時服務端的響應。這裡一定要給錯誤處理中介軟體的處理函式 四個引數, 切記。在應用程式級別的中介軟體 app.get() 中,當非同步讀取檔案失敗時,記得要把錯誤物件傳遞給next()方法 。通過這樣,一旦 index.html 檔案丟失,請求則會進入錯誤處理中介軟體,傳送錯誤物件的具體訊息給到瀏覽器響應。

  1. Built-in middleware(內建中介軟體)

express為我們也提供了一些內建中介軟體,比如常見的開放靜態資源: express.static()等。

const express = require('express')

const app = express()

// 開放公共資源
app.use('/public/', express.static('./public'))
  1. Third-party middleware(第三方中介軟體)

同樣,我們也可以使用別人封裝好的第三方中介軟體,第三方中介軟體都是一個個第三方包,所以使用前需要我們單獨下載到專案中。之前的 body-parser 中介軟體,就是用來解析 post 請求體的資料,還有常見的像 express-session 中介軟體, cookie-parser用來獲取請求的cookie 資料等。第三方中介軟體具體可以檢視 express 官方 API,這裡就不再一一羅列 。

官方推薦的第三方中介軟體:第三方中介軟體

寫在後面

因為文章內容是自己空閒時間編寫,如果您發現有哪些錯誤可以在GitHub上提交 issue ,也可以在留言區發表評論,這樣可以方便於後來的同學學習,謝謝啦~

相關文章