欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

NodeJs Express中間件使用流程解析

 更新時(shí)間:2023年01月10日 09:46:18   作者:落雪小軒韓  
Express中間件本質(zhì)上就是一個(gè)function處理函數(shù),多個(gè)中間件之間,共享同一份req和res,我們就可以在上游的中間件中統(tǒng)一為req或者res對(duì)象添加自定義的屬性或方法,供下游的中間件或路由進(jìn)行使用,非常方便

中間件(Middleware),特指業(yè)務(wù)流程的中間處理環(huán)節(jié)

1、調(diào)用流程

當(dāng)一個(gè)請(qǐng)求到達(dá)Express的服務(wù)器之后,可以連續(xù)調(diào)用多個(gè)中間件,從而對(duì)這次請(qǐng)求進(jìn)行預(yù)處理。

2、格式

Express的中間件,本質(zhì)上就是一個(gè)function處理函數(shù),Express中間件的格式如下:

app.get('/',(req,res,next) => {
	next()
})

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

3、next函數(shù)的作用

next函數(shù)是實(shí)現(xiàn)多個(gè)中間件連續(xù)調(diào)用的關(guān)鍵,它表示把流轉(zhuǎn)關(guān)系轉(zhuǎn)交給下一個(gè)中間件或路由

4、定義中間件函數(shù)

const vm = function(req,res,next) {
  console.log('這是最簡(jiǎn)單的中間件函數(shù)');
  // 把流轉(zhuǎn)關(guān)系轉(zhuǎn)交給下一個(gè)中間件或路由
  next()
}

5、全局生效的中間件

客戶端發(fā)起的任何請(qǐng)求,到達(dá)服務(wù)器之后,都會(huì)觸發(fā)的中間件

通過(guò)app.use(中間件函數(shù)),即可定義一個(gè)全局生效的中間件

const vm = function(req,res,next) {
  console.log('這是最簡(jiǎn)單的中間件函數(shù)');
  // 把流轉(zhuǎn)關(guān)系轉(zhuǎn)交給下一個(gè)中間件或路由
  next()
}
app.use(vm)

6、中間件的作用

多個(gè)中間件之間共享一份reqres??梢栽谏嫌蔚闹虚g件中,統(tǒng)一為 req 或 res 對(duì)象添加自定義的屬性或方法,供下游的中間件或路由進(jìn)行使用。

7、定義多個(gè)全局中間件

可以使用app.use()連續(xù)定義多個(gè)全局中間件??蛻粽?qǐng)求到達(dá)服務(wù)器之后,會(huì)按照中間件定義的先后順序依次進(jìn)行調(diào)用

app.use(function(req,res,next) {
  console.log('調(diào)用了第一個(gè)中間件');
  next()
})
app.use(function(req,res,next) {
  console.log('調(diào)用了第二個(gè)中間件');
  next()
})
app.get('/',(req,res) => {
  res.send('OK.')
})

當(dāng)請(qǐng)求http://127.0.0.1/時(shí)

8、局部生效的中間件

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

const vm = function(req,res,next) {
  console.log('調(diào)用了局部生效的中間件');
  next()
}
app.get('/',vm,(req,res) => {
  res.send('Home Page.')
})
app.get('/user',vm,(req,res) => {
  res.send('User Page.')
})

vm中間件只會(huì)在/路由中生效,不會(huì)影響其他的路由。當(dāng)請(qǐng)求http://127.0.0.1/時(shí)控制臺(tái)有打印,請(qǐng)求http://127.0.0.1/user時(shí),控制臺(tái)沒(méi)有打印。

9、定義多個(gè)局部中間件

app.get('/',mw1,mw2,(req,res) => {})
app.get('/',[mw1,mw2],(req,res) => {})

如上兩種寫法是等價(jià)的

10、了解中間件的注意事項(xiàng)

① 一定要在路由之前注冊(cè)中間件

② 客戶端發(fā)過(guò)來(lái)的請(qǐng)求,可以連續(xù)調(diào)用多個(gè)中間件進(jìn)行處理

③ 執(zhí)行完中間件的業(yè)務(wù)代碼之后,要調(diào)用 next() 函數(shù)

④ 為了防止代碼邏輯混亂,調(diào)用 next() 函數(shù)后不要再寫額外的代碼

⑤ 連續(xù)調(diào)用多個(gè)中間件時(shí),多個(gè)中間件之間共享 req 和 res 對(duì)象

11、中間件的分類

1、應(yīng)用級(jí)別的中間件

通過(guò) app.use() 或 app.get() 或 app.post(),綁定到 app 實(shí)例上的中間件

2、路由級(jí)別的中間件

綁定到 express.Router()路由實(shí)例上的中間件

var app = express()
var router = express.Router()
router.use(function(req,res,next) {})

3、錯(cuò)誤級(jí)別的中間件

專門用來(lái)捕獲整個(gè)項(xiàng)目中發(fā)生的異常信息,從而防止項(xiàng)目異常崩潰的問(wèn)題

格式:function處理函數(shù)中,必須有4個(gè)形參,從前到后分別是(err、req、res、next)

app.get('/',(req,res) => {
	throw new Error('服務(wù)器內(nèi)部發(fā)生了錯(cuò)誤!')
	res.send('Home Page.')
})

此時(shí)通過(guò)http://127.0.0.1/訪問(wèn)服務(wù)器,服務(wù)器就發(fā)生了崩潰

// 定義錯(cuò)誤級(jí)別的中間件捕獲整個(gè)項(xiàng)目的異常錯(cuò)誤,從而防止程序的崩潰
app.use((err,req,res,next) => {
	res.send('Error:' + err.message)
})

此時(shí)通過(guò)http://127.0.0.1/訪問(wèn)服務(wù)器,服務(wù)器雖然發(fā)生了錯(cuò)誤,但是沒(méi)有崩潰

注意:錯(cuò)誤級(jí)別的中間件必須注冊(cè)在所有路由之后

4、Express內(nèi)置的中間件

自 Express 4.16.0 版本開(kāi)始,Express內(nèi)置了3個(gè)常用的中間件,極大的提高了Express項(xiàng)目的開(kāi)發(fā)效率和體驗(yàn)

express.static

快速托管靜態(tài)資源的內(nèi)置中間件,例如:HTML文件、圖片、CSS樣式等(無(wú)兼容性)

express.json

解析 JSON 格式的請(qǐng)求體數(shù)據(jù)(有兼容性,僅在 4.16.0+版本中可用)

app.post('/user',(req,res) => {
	// 通過(guò) req.body 來(lái)接收客戶端發(fā)送過(guò)來(lái)的請(qǐng)求體數(shù)據(jù)
	console.log(req.body)
	res.send('ok')
})

訪問(wèn) http://127.0.0.1/user,并使用post請(qǐng)求發(fā)送JSON格式的參數(shù),如 {"name":"zs","age":18}

如上打印 req.body 值為 undefined

app.use(express.json())
app.post('/user',(req,res) => {
	console.log(req.body)
	res.send('ok')
})

配置了解析JSON格式的請(qǐng)求體數(shù)據(jù)的中間件,打印 req.body 值為 {name:'zs',age:'18'}

express.urlencoded

解析 URL-encoded 格式的請(qǐng)求體數(shù)據(jù)(有兼容性,僅在 4.16.0+版本中可用)

app.post('/user',(req,res) => {
	console.log(req.body)
	res.send('ok')
})

訪問(wèn) http://127.0.0.1/user,并使用post請(qǐng)求發(fā)送x-www-form-urlencoded格式的參數(shù),如 key:name,value:zskey:age,value:18,如上打印 req.body 值為 undefined

app.use(express.json())
app.post('/user',(req,res) => {
	console.log(req.body)
	res.send('ok')
})

配置的是解析JSON格式的請(qǐng)求體數(shù)據(jù)的中間件,打印 req.body 值為 {}

app.use(express.urlencoded({extended:false}))
app.post('/user',(req,res) => {
	console.log(req.body)
	res.send('ok')
})

配置了解析表單中 urlencoded 格式的請(qǐng)求體數(shù)據(jù)的中間件,打印 req.body 值為 {name:'zs',age:'18'}

5、第三方中間件

非 Express 官方內(nèi)置的,而是由第三方開(kāi)發(fā)出來(lái)的中間件為第三方中間件??梢园葱柘螺d并配置,從而提高項(xiàng)目的開(kāi)發(fā)效率

body-parser這個(gè)第三方中間件用來(lái)解析請(qǐng)求體數(shù)據(jù)

① 運(yùn)行 npm i body-parser

② 使用 require導(dǎo)入中間件

③ 調(diào)用app.use()注冊(cè)并使用中間件

const parser = require('body-parser')
app.use(parser.urlencoded({extended:false}))

注意:Express內(nèi)置的express.urlencoded中間件,就是基于body-parser這個(gè)第三方中間件進(jìn)一步封裝出來(lái)的

6、自定義中間件

手動(dòng)模擬一個(gè)類似于 express.urlencoded 的中間件,來(lái)解析POST提交到服務(wù)器的表單數(shù)據(jù)

① 定義中間件

② 監(jiān)聽(tīng) req 的 data 事件

③ 監(jiān)聽(tīng) req 的 end 事件

④ 使用 querystring 模塊解析請(qǐng)求體數(shù)據(jù)

⑤ 將解析出來(lái)的數(shù)據(jù)對(duì)象掛載為 req.body

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

1、定義中間件

app.use((req,res,next) => {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->})

2、監(jiān)聽(tīng) req 的 data 事件

監(jiān)聽(tīng) req 對(duì)象的 data 事件來(lái)獲取客戶端發(fā)送到服務(wù)器的數(shù)據(jù)。

如果數(shù)據(jù)量比較大無(wú)法一次性發(fā)送完畢,則客戶端會(huì)把數(shù)據(jù)切割后分批發(fā)送到服務(wù)器,每次觸發(fā) data 事件獲取到的數(shù)據(jù)只是完整數(shù)據(jù)的一部分,需要手動(dòng)對(duì)接收的數(shù)據(jù)進(jìn)行拼接

app.use((req,res,next) => {
  // 1. 定義一個(gè)變量,專門用來(lái)存儲(chǔ)客戶端發(fā)送過(guò)來(lái)的請(qǐng)求體數(shù)據(jù)
  let str = ''
  // 2. 監(jiān)聽(tīng)req的data事件
  req.on('data',(chunk) => {
    str += chunk
  })
})

3、監(jiān)聽(tīng) req 的 end 事件

當(dāng)請(qǐng)求體數(shù)據(jù)接收完畢之后,會(huì)自動(dòng)觸發(fā) req 的 end 事件

app.use((req,res,next) => {
  let str = ''
  req.on('data',(chunk) => {
    str += chunk
  })
  // 3.監(jiān)聽(tīng)req的end事件
  req.on('end',() => {
    // 在str中存放的是完整的請(qǐng)求體數(shù)據(jù)
    console.log(str);
  })
})

得到的值為:name=zs&age=18&gender=%E7%94%B7

4、使用 querystring 模塊解析請(qǐng)求體數(shù)據(jù)

Node.js 內(nèi)置了一個(gè) querystring 模塊,專門用來(lái)處理查詢字符串。通過(guò)這個(gè)模塊提供的 parse() 函數(shù),可以把查詢字符串解析成對(duì)象的格式

const qs = require('querystring')
app.use((req,res,next) => {
  let str = ''
  req.on('data',(chunk) => {
    str += chunk
  })
  req.on('end',() => {
    // 4.把字符串格式的請(qǐng)求體數(shù)據(jù)解析成對(duì)象格式
    const body = qs.parse(str)
    console.log(body)
  })
})

得到的值為:{ name: 'zs', age: '18', gender: '男' }

5、將解析出來(lái)的數(shù)據(jù)對(duì)象掛載為 req.body

上游的中間件和下游的中間件及路由之間共享同一份 reqres。因此可以將解析出來(lái)的數(shù)據(jù)掛載為 req 的自定義屬性,命名為 req.body 供下游使用

const qs = require('querystring')
app.use((req,res,next) => {
  let str = ''
  req.on('data',(chunk) => {
    str += chunk
  })
  req.on('end',() => {
    const body = qs.parse(str)
    // 5. 將解析出來(lái)的請(qǐng)求體對(duì)象掛載為 req.body 屬性,最后要調(diào)用 next() 函數(shù)執(zhí)行后續(xù)的業(yè)務(wù)邏輯
    req.body = body
    next()
  })
})

6、將自定義中間件封裝為模塊

把自定義的中間件函數(shù)封裝為獨(dú)立的模塊 custom-body-parser.js

const qs = require('querystring')
const bodyParser = function(req,res,next) {
  let str = ''
  req.on('data',(chunk) => {
    str += chunk
  })
  req.on('end',() => {
    const body = qs.parse(str)
    req.body = body
    next()
  })
}
module.exports = bodyParser

使用:

// 導(dǎo)入自己封裝的中間件模塊
const customBodyParser = require('./custom-body-parser')
// 將自定義的中間件函數(shù)注冊(cè)為全局可用的中間件
app.use(customBodyParser)

到此這篇關(guān)于NodeJs Express中間件使用流程解析的文章就介紹到這了,更多相關(guān)NodeJs Express中間件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Node.js中處理特殊字符的文件名解決方案

    Node.js中處理特殊字符的文件名解決方案

    在Node.js中,通過(guò)path模塊提供的basename方法,我們可以輕松地從文件路徑中提取文件名,在這篇文章中,我們將介紹一種安全穩(wěn)妥的方法,結(jié)合使用dirname和長(zhǎng)度計(jì)算,以處理特殊字符的文件名,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • node.js實(shí)現(xiàn)為PDF添加水印的示例代碼

    node.js實(shí)現(xiàn)為PDF添加水印的示例代碼

    這篇文章主要介紹了node.js實(shí)現(xiàn)為PDF添加水印的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • 如何讓Nodejs支持H5 History模式(connect-history-api-fallback源碼分析)

    如何讓Nodejs支持H5 History模式(connect-history-api-fallback源碼分析)

    這篇文章主要介紹了如何讓Nodejs支持H5 History模式(connect-history-api-fallback源碼分析),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-05-05
  • NodeJS GRPC簡(jiǎn)單的示例詳解

    NodeJS GRPC簡(jiǎn)單的示例詳解

    本文介紹了如何使用NodeJS GRPC,包括.proto文件的定義、客戶端和服務(wù)器的實(shí)現(xiàn),首先,創(chuàng)建.proto文件定義服務(wù)和消息,然后實(shí)現(xiàn)客戶端greeter_client.js文件,最后運(yùn)行服務(wù)器和客戶端,通過(guò)這篇文章,你可以快速掌握NodeJS GRPC的基礎(chǔ)使用方法
    2024-10-10
  • 使用nodejs連接mySQL寫接口全過(guò)程(增刪改查)

    使用nodejs連接mySQL寫接口全過(guò)程(增刪改查)

    這篇文章主要給大家介紹了關(guān)于使用nodejs連接mySQL寫接口(增刪改查)的相關(guān)資料,MySQL是一種常用的關(guān)系型數(shù)據(jù)庫(kù),它與Node.js的結(jié)合可以提供強(qiáng)大的數(shù)據(jù)存儲(chǔ)和檢索功能,需要的朋友可以參考下
    2023-12-12
  • 淺談Node 調(diào)試工具入門教程

    淺談Node 調(diào)試工具入門教程

    這篇文章主要介紹了淺談Node 調(diào)試工具入門教程,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • 了不起的node.js讀書(shū)筆記之node.js中的特性

    了不起的node.js讀書(shū)筆記之node.js中的特性

    這篇文章主要介紹了了不起的node.js讀書(shū)筆記之node.js中的特性,需要的朋友可以參考下
    2014-12-12
  • Node.JS更改Windows注冊(cè)表Regedit的方法小結(jié)

    Node.JS更改Windows注冊(cè)表Regedit的方法小結(jié)

    注冊(cè)表是windows操作系統(tǒng)中的一個(gè)核心數(shù)據(jù)庫(kù),這里介紹一些通過(guò)node.js操作注冊(cè)表的幾種方法,感興趣的朋友參考下吧
    2017-08-08
  • nodejs服務(wù)搭建教程 nodejs訪問(wèn)本地站點(diǎn)文件

    nodejs服務(wù)搭建教程 nodejs訪問(wèn)本地站點(diǎn)文件

    這篇文章主要為大家詳細(xì)介紹了nodejs服務(wù)搭建教程,訪問(wèn)本地站點(diǎn)文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • nodejs配置express服務(wù)器運(yùn)行自動(dòng)打開(kāi)瀏覽器詳細(xì)步驟

    nodejs配置express服務(wù)器運(yùn)行自動(dòng)打開(kāi)瀏覽器詳細(xì)步驟

    在nodejs中使用express來(lái)搭建框架可以說(shuō)是非常的簡(jiǎn)單方便,下面這篇文章主要給大家介紹了關(guān)于nodejs配置express服務(wù)器運(yùn)行自動(dòng)打開(kāi)瀏覽器的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01

最新評(píng)論