Node.js基礎---Express中間件

1. 概念

1.什么是中間件

? ? ? ? 中間件(Middleware),特指業務流程的中間處理環節

2. Express 中間件的調用流程

? ? ? ? 當一個請求到達 Express 的服務器后,可以連續調用多個中間件,從而對這次請求進行預處理

3. Express 中間件格式

? ? ? ?Express 的中間件,本質上是一個 function 處理函數,Express 中間件格式如下

? ? ? ? 中間件函數的形參列表中,必須包含 next 參數,而路由處理函數中只包含 req 和 res

4. next 函數的作用

? ? ? ? next 函數是實現多個中間件連續調用的關鍵,它表示把流轉關系轉交給下一個中間件或者路由

2. 中間件函數

1.?定義

// 常量 mv 所指向的就是一個中間件函數
const mv = function ( req, res, next) {console.log('中間件demo')// 注意: 在當前中間件的業務處理完畢后,必須調用 next() 函數// 表示把流轉關系轉交給下一個中間件或路由next()
}

2. 全局生效的中間件

? ? ? ? 客戶端發起的任何請求,到達服務器后,都會觸發的中間件,叫全局生效的中間件

? ? ? ? 通過調用 app.use(中間件函數),即可定義一個全局生效的中間件

// 常量 mv 所指向的就是一個中間件函數
const mv = function ( req, res, next) {console.log('中間件demo')next()
}// 全局生效的中間件
app.use(mv)

3. 定義全局中間件的簡化形式

// 全局生效的中間件
app.use(function (req, res, next){console.log('demo')next()
})

4. 中間件的作用

? ? ? ? 多個中間件之間,共享同一份 req 和 res,基于這樣的特性,我們可以在上游的中間件中,統一為 req 或 res 對象添加自定義的屬性或方法,供下游的中間件或路由進行使用

5. 定義多個全局中間件

? ? ? ? 可以使用 app.use() 連續定義多個全局中間件,客戶端請求到達服務器后,會按照中間件定義的先后順序依次進行調用

6. 局部生效的中間件

? ? ? ? 不使用?app.use() 定義的中間件,即局部生效的中間件

? ? ? ? 只在當前路由生效

const mv1 = function(req, res, next) {console.log('中間件函數')next()
}// mv1 中間件只在當前路由生效
app.get('/', mv1, function(req, res) {res,send('get')
})// 此路由不生效
app.get('/user', function(req, res) {res,send('get1')
})

7. 定義多個局部中間件

? ? ? ? 兩種等價方式定義

app.get('/', mv1, mv2, function(req, res) { res,send('get') })
app.get('/', [mv1, mv2], function(req, res) { res,send('get') })

8. 中間件的5個使用注意事項

? ? ? ? ①? 一定要在路由之前注冊中間件

? ? ? ? ②? 客戶端發送的請求,可以連續調用多個中間件進行處理

? ? ? ? ③? 執行完中間件的業務代碼,需要調用 next() 函數

? ? ? ? ④? 防止代碼邏輯混亂,調用完?next() 函數后不要再寫額外代碼?

? ? ? ? ⑤? 連續多個中間件時,多個中間件之間,共享 req 和 res 對象

3. 中間件的分類

? ? ? ? Express 官方把常見的中間件用法,分為了五大類

? ? ????????? ? ①? 應用級別的中間件

? ? ????????? ? ②? 路由級別的中間件

? ? ????????? ? ③? 錯誤級別的中間件

? ? ? ????????? ④? Express 內置的中間件

? ? ????????? ? ⑤? 第三方的中間件

1.?應用級別的中間件

? ? ? ? 通過 app.use() 或 app.get() 或 app.post()綁定到app實例上的中間件,叫做應用級別的中間件? ? ? ? 全局中間件和局部中間件

// 應用級別的中間件 (全局中間件)
app.use((req, res, next) => {next()
})// 應用級別的中間件 (局部中間件)
app.get('/', mv1, (req, res, next) => {res.send('局部')
})

2. 路由級別的中間件?

? ? ? ? 綁定到 express.Router() 實例上的中間件,叫做路由級別的中間件,它的用法和應用級別中間件沒有區別,區別在于,應用級別中間件是綁定在 app 實例上的,路由級別中間件綁定到 router 實例上的

const app = express()
const router = express.Router()// 路由級別的中間件
router.use(function (req, res, next) {console.log('路由級別中間件')next()
})app.use('/', router)

3. 錯誤級別的中間件

? ? ? ? 作用:專門用來捕獲整個項目中發生的異常錯誤,從而防止項目異常崩潰的問題

????????格式:必須要有 4 個形參,從前到后分別是 (err, req, res, next)

app.get('/', function(req, res) {            // 路由throw new Error('錯誤!')                 // 拋出自定義錯誤res.send('get')
})
app.use(function (err, req, res, next) {    // 錯誤級別的中間件        console.log('發生了錯誤' + err.message)  // 服務器打印錯誤消息res,send('Error' + err.message)         // 向客戶端響應錯誤信息相關內容
})

? ? ? ? 注意:錯誤級別的中間件,必須注冊在所有路由之后

4. Express內置的中間件

? ? ? ? Express 4.16.0版本后,Express 內置了3個常用的中間件

? ? ? ? ①? express.static 快速托管靜態資源的內置中間件,例如:HTML文件,圖片,css樣式(無兼容性

? ? ? ? ②? express.json 解析JSON格式的請求體數據(有兼容性,在4.16.0+版本可用)

? ? ? ? ③? express.urlencoded 解析 URL-encoded 格式的請求體數據(有兼容性,在4.16.0+版本可用)

// 配置解析 application/json 格式數據的內置中間件
app.use(express.json())
// 配置解析 application/x-www-form-urlencode 格式數據的內置中間件
app.use(express.urlencoded({ extend: false }))

5. 第三方的中間件

? ? ? ? 非 Express 官方內置的,是第三方開發出來的中間件,叫第三方中間件,項目中可以按需下載并配置第三方中間件

? ? ? ? 在 express@4.16.0 之前的版本中,經常使用 body-parser 第三方中間件來解析請求體數據:

? ? ? ? ①? 運行 npm i body-parser 安裝

? ? ? ? ②??使用 require 導入中間件

? ? ? ? ③? 調用 app.use() 注冊并使用中間件

? ? ? ? 注意:Express 內置的?express.urlencoded 中間件,就是基于?body-parser 進一步封裝的

4.? 自定義中間件

1. 需求描述與實現步驟

????????需求:手動模擬類似于?express.urlencoded 的中間件,解析POST提交到服務器的表單數據

? ? ? ? 實現步驟:

? ? ? ? ? ? ? ? ①? ?定義中間件

? ? ? ? ? ? ? ? ②? ?監聽 req 的 data 事件

? ? ? ? ? ? ? ? ③? ?監聽 req 的 end 事件

? ? ? ? ? ? ? ? ④? ?使用 queryString 模塊解析請求體數據

? ? ? ? ? ? ? ? ⑤? ?將解析出來的數據對象掛載為 req.body

? ? ? ? ? ? ? ? ⑥? ?將自定義中間件封裝為模塊

2. 定義中間件

? ? ? ? 使用 app.use() 定義全局生效的中間件

app.use(function(req, res, next){// 中間件的業務邏輯
})

3.?監聽 req 的 data 事件

? ? ? ? 獲取客戶端發送到服務器的數據

? ? ? ? 如果數據量比較大,無法一次性發送完畢,則客戶端會把數據切割后,分批發送到服務器。所以data事件可能會觸發多次,每次觸發。獲取到數據只是完整數據的一部分,需要手動對接收到的數據進行拼接

// 定義變量 儲存客戶端發來的請求體數據
let str = ''
// 監聽 req 對象的 data 事件
req.on('data', (chunk) => {// 拼接請求體數據,隱式轉換為字符串str += chunk
})

4.?監聽 req 的 end 事件

? ? ? ? 請求體數據接收完畢之后會自動觸發 req 的 end 事件

? ? ? ? 可以在 req 的 end 事件中,拿到并處理完整的請求體數據

// 監聽 req 對象的 end 事件
req.on('end', () => {console.log(str) // 打印完整請求體數據// TOOD: 把字符串的請求體數據,解析成對象格式
})

5.?使用 queryString 模塊解析請求體數據

? ? ? ? Node.js 內置了一個 querystring 模塊,專門用來處理查詢字符串。通過這個模塊提供的 parse(), 可以把查詢字符串解析成對象的格式

// 導入處理 querystring 的 Node.js 內置模塊
const qs = require('querystring')// 調用 qs.parse() 方法 把查詢字符串解析為對象
const body = qs.parse(str)

? ? ? ? 注意:qs被棄用

6.?將解析出來的數據對象掛載為 req.body

? ? ? ? 上游中間件和下游中間件及路由之間,共享同一份 req 和 res。可以將解析出來的數據,掛載為 req 的自定義屬性,命名為 req.body,供下游使用

req.on('end', () => {const body = qs.parse(srt)    // 調用 qs.parse() 方法把查詢字符串解析成對象req.body = body               // 解析出來的請求體對象瓜子next()                        // 調用 next(),執行后續邏輯
})    

7.?將自定義中間件封裝為模塊

? ? ? ? 優化結構,封裝為獨立模塊

// custom-body-parser.js 模塊代碼
const qs = require('querystring')
function bodyParser(req, res, next){ /* 省略 */ }
module.export = bodyParser // 向外導出解析請求體孫書記的中間件函數---------------------------------------------// 1. 導入自定義的中間件模塊
const myBodyParser = require('custom-body-parse')
// 2. 注冊自定義的中間件模塊
app.use(myBodyParser )

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/713437.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/713437.shtml
英文地址,請注明出處:http://en.pswp.cn/news/713437.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

每周一算法:雙端隊列廣搜

題目鏈接 電路維修 題目描述 達達是來自異世界的魔女,她在漫無目的地四處漂流的時候,遇到了善良的少女翰翰,從而被收留在地球上。翰翰的家里有一輛飛行車。有一天飛行車的電路板突然出現了故障,導致無法啟動。 電路板的整體結…

Java實戰:SpringBoot集成ZXing實現二維碼生成與解析

一、引言 在信息化社會,二維碼已經深入到生活的各個角落,無論是支付、營銷、信息傳遞,甚至防偽溯源,二維碼都發揮了至關重要的作用。作為Java開發者,我們如何在SpringBoot項目中便捷地實現二維碼的生成與解析呢&#…

4、Redis-Set【常用】

目錄 一、Redis-Set特點 二、常用命令與交并差 三、Redis中Set類型應用場景 一、Redis-Set特點 1、無序:添加的是A,B,C;取出的可能是B,A,C 2、唯一:不允許元素重復 二、常用命令與交并差 常用命令 格式含義例子sadd key members[...]往k…

吳恩達機器學習筆記十四 多輸出的分類 多類和多標簽的區別 梯度下降優化 卷積層

這里老師想講的是multiclass classification和multilable classification的區別,下面是我從其他地方找到的說法: Multiclass classification 多類分類 意味著一個分類任務需要對多于兩個類的數據進行分類。比如,對一系列的橘子,蘋果或者梨的…

Stable Diffusion生成式擴散模型代碼實現原理

Stable Diffusion可以使用PyTorch或TensorFlow等深度學習框架來實現。這些框架提供了一系列的工具和函數,使得開發者可以更方便地構建、訓練和部署深度學習模型。因此可以使用PyTorch或TensorFlow來實現Stable Diffusion模型。 安裝PyTorch:確保您已經安…

Linux命令行與shell腳本編程大全-2.2

第二部分 shell腳本編程基礎 第11章構建基礎腳本 第12章結構化命令 第13章更多的結構化命令 第14章處理用戶輸入 第15章呈現數據 第16章腳本控制 第15章 呈現數據 15.1 理解輸入和輸出 15.1.1 標準文件描述符 Linux 系統會將每個對象當作文件來處理,這包括輸入和…

T3SF:一款功能全面的桌面端技術練習模擬框架

關于T3SF T3SF是一款功能全面的桌面端技術練習模擬框架,該工具針對基于主場景事件列表的各種事件提供了模塊化的架構,并包含了針對每一個練習定義的規則集,以及允許為對應平臺參數定義參數的配置文件。 該工具的主模塊能夠執行與其他特定模…

CDN原理探究

來源于百度: https://baike.baidu.com/item/%E5%86%85%E5%AE%B9%E5%88%86%E5%8F%91%E7%BD%91%E7%BB%9C/4034265?frge_ala 通過上圖,我們可以了解到,使用了CDN緩存后的網站的訪問過程變為: 用戶向瀏覽器提供要訪問的域名&#xff…

幻獸帕魯/Palworld服務器的最佳網絡設置、內存和CPU配置是什么?

幻獸帕魯/Palworld服務器的最佳網絡設置、內存和CPU配置是什么? 對于4到8人的玩家,推薦的配置是4核16G的CPU和16G的內存。10到20人的玩家選擇8核32G的CPU和32G或以上的內存。2到4人的玩家則建議選擇4核8G的CPU和8G的內存。對于32人的玩家,推…

YOLOV8介紹

原文鏈接: 1、 詳解YOLOv8網絡結構/環境搭建/數據集獲取/訓練/推理/驗證/導出 2、Yolov8的詳解與實戰 3、YOLOV8模型訓練部署(實戰)()有具體部署和訓練實現代碼YOLOV8模型訓練部署(實戰)&…

Mybatis plus核心功能-IService

目錄 1 前言 2 使用方法 2.1 繼承ServiceImpl,> 2.2 基礎業務開發的使用 2.3 復雜業務開發的使用 2.3 Lambda查詢 2.4 Lambda更新 1 前言 我本以為Mapper層的類能夠繼承BaseMapper<XXX>&#xff0c;而不用我們手動寫一些mapper方法已經夠離譜了。沒想到海油膏…

linux上pip3 install torch==1.11和pip3 install torch==1.11+cu115區別

在linux上安裝torch時&#xff0c; 如果環境安裝好了CUDA環境&#xff0c; 那么安裝torch時不用刻意指定帶cuda的版本&#xff0c; 最終安裝的也是支持GPU的torch版本。但是仍然有一些小的區別&#xff0c;主要就是支持CUDA版本的不同。 (leo_py37) pinefieldedge-gpu-01:/dat…

Gradle構建項目

1.自己下載對應的gradle版本到本地。 2.maven國內鏡像&#xff08;settings.gradle中進行配置&#xff09; // google()maven { url https://maven.aliyun.com/repository/public/ }maven { url https://maven.aliyun.com/repository/google/}maven { url https://maven.aliyu…

【機器學習300問】25、常見的模型評估指標有哪些?

模型除了從數據劃分的角度來評估&#xff0c;我上一篇文章介紹了數據集劃分的角度&#xff1a; 【機器學習300問】24、模型評估的常見方法有哪些&#xff1f;http://t.csdnimg.cn/LRyEt 還可以從一些指標的角度來評估&#xff0c;這篇文章就帶大家從兩個最經典的任務場景介紹…

Day08:基礎入門-算法分析傳輸加密數據格式密文存儲代碼混淆逆向保護

目錄 傳輸數據-編碼型&加密型等 傳輸格式-常規&JSON&XML等 密碼存儲-Web&系統&三方應用 代碼混淆-源代碼加密&逆向保護 思維導圖 章節知識點&#xff1a; 應用架構&#xff1a;Web/APP/云應用/三方服務/負載均衡等 安全產品&#xff1a;CDN/WAF/I…

【stata】漸進式雙重差分/交錯式雙重差分(staggered-DID) 實現過程

Staggered-DID 的實現 為保證本貼的簡潔性與一般適用性,本文并沒有使用現有真實數據,而是模擬了一個一般數據。如果你手中有正在處理好的project數據,可以跳過1.數據生成,直接從2.數據預加工開始。 1.數據生成 (1)數據生成過程 我將隨機生成一個數據來模擬staggered-DID…

leetcode 熱題 100_移動零

題解一&#xff1a; 雙指針遍歷&#xff1a;將非零的值往數組前端依次放置&#xff0c;將放置之后數組后端多余的位置都置為0&#xff0c;參考下圖&#xff08;來源. - 力扣&#xff08;LeetCode&#xff09;&#xff09; class Solution {public void moveZeroes(int[] nums)…

c語言的數據結構:隊列

1.隊列存在的實現方式及其存在意義 1.1為什么隊列使用單鏈表實現更好 動態內存分配&#xff1a;鏈表在C語言中通常使用動態內存分配&#xff0c;這意味著可以在運行時根據需要動態地添加或刪除節點。這對于實現一個動態大小的隊列非常有用&#xff0c;因為隊列的大小可以在運…

界面控件Telerik UI for ASP. NET Core教程 - 如何為網格添加上下文菜單?

Telerik UI for ASP.NET Core是用于跨平臺響應式Web和云開發的最完整的UI工具集&#xff0c;擁有超過60個由Kendo UI支持的ASP.NET核心組件。它的響應式和自適應的HTML5網格&#xff0c;提供從過濾、排序數據到分頁和分層數據分組等100多項高級功能。 上下文菜單允許開發者為應…

[unity] c# 擴展知識點其一 【個人復習筆記/有不足之處歡迎斧正/侵刪】

.NET 微軟的.Net既不是編程語言也不是框架,是類似于互聯網時代、次時代、21世紀、信息時代之類的宣傳口號,是一整套技術體系的統稱&#xff0c;或者說是微軟提供的技術平臺的代號. 1.跨語言 只要是面向.NET平臺的編程語言(C#、VB、 C、 F#等等)&#xff0c;用其中一種語言編寫…