您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)express.js框架中間件的示例分析的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。
_express.js_作為_(kāi)Node.js_的老牌框架,是現(xiàn)有框架中最全面的。然而在學(xué)習(xí)express除了那些api之外,對(duì)于框架最重要的就是__中間件__這個(gè)概念了。如果理解了,就可以把這個(gè)框架玩活了,項(xiàng)目開(kāi)發(fā)肯定會(huì)更加順利,而且還可以開(kāi)發(fā)很多額外的功能,甚至中間件擴(kuò)展開(kāi)發(fā)。
但是就這么一個(gè)東西,是很多學(xué)習(xí)node.js的小萌新們就算寫(xiě)出一個(gè)博客項(xiàng)目,都不知道它到底有啥作用。我當(dāng)時(shí)在理解的時(shí)候也花了不少功夫,趁著沒(méi)有啥工作,給各位學(xué)習(xí)express.js的一點(diǎn)點(diǎn)我的指導(dǎo)意見(jiàn)。當(dāng)然,這里面可能也有koa2和egg的忠實(shí)粉絲,但其實(shí)所有node框架貌似都有這個(gè)概念,所以我用express舉例子,希望各位將就一下哈,應(yīng)該都是可以看得懂的。
首先我先來(lái)一波官方的解釋:
好吧,被這些英語(yǔ)嚇到了,來(lái)一波譯文:
[中間件函數(shù)是可以訪問(wèn)請(qǐng)求對(duì)象(req)、響應(yīng)對(duì)象(res)和應(yīng)用程序請(qǐng)求響應(yīng)周期中的下一個(gè)函數(shù)的函數(shù)。下一個(gè)函數(shù)是Express路由器中的一個(gè)函數(shù),當(dāng)調(diào)用該函數(shù)時(shí),它執(zhí)行當(dāng)前中間件之后的中間件。
中間件功能可以執(zhí)行以下任務(wù):
執(zhí)行任何代碼
對(duì)請(qǐng)求和響應(yīng)對(duì)象進(jìn)行更改。
結(jié)束請(qǐng)求響應(yīng)周期。
調(diào)用堆棧中的下一個(gè)中間件。
終于知道當(dāng)初的我為毛剛開(kāi)始理解的時(shí)候很困難了,說(shuō)實(shí)在的看得我真的有懵的。幸好,我還是從這個(gè)坑爬出來(lái)了,我來(lái)拉你們一把了。首先我們不去深究概念,直接上一個(gè)代碼塊。
如果我們啟動(dòng)服務(wù),訪問(wèn)'/'路由,會(huì)返回"這是一個(gè)根路由",訪問(wèn)router1路由就會(huì)得到這是一個(gè)"這是一個(gè)router1路由的"的信息。這看起來(lái)是一個(gè)很簡(jiǎn)單的路由查詢,我們理一下過(guò)程,這個(gè)請(qǐng)求是如何訪問(wèn)到這個(gè)路由的呢。
一般來(lái)說(shuō),一個(gè)express框架的項(xiàng)目會(huì)寫(xiě)入很多路由,但各位要注意的是,這個(gè)請(qǐng)求并不是直接定位到這個(gè)路由的,而是一個(gè)從上至下匹配的一個(gè)過(guò)程。
有點(diǎn)亂?沒(méi)關(guān)系我們看圖
我們看到這幅圖,有一個(gè)箭頭,從上到下的。什么意思呢,如果用戶發(fā)了一個(gè)這樣的請(qǐng)求
GET '/router7'
那么他會(huì)從第一個(gè)開(kāi)始一個(gè)一個(gè)去匹配,知道發(fā)現(xiàn)有一個(gè)路由名和請(qǐng)求方法都一致的路由,就立馬執(zhí)行里面的代碼,并且返回一段文字"這是一個(gè)router7路由"。這都很好理解,那么現(xiàn)在我有一個(gè)需求,就是不管訪問(wèn)任何一個(gè)路由,我都要知道這個(gè)訪問(wèn)者的ip地址和訪問(wèn)的目標(biāo)路由打印出來(lái),生產(chǎn)訪問(wèn)日志。那么怎么做了。
我們分析一波,這段程序是所有的請(qǐng)求都要執(zhí)行的,如果按照?qǐng)?zhí)行順序的說(shuō)法,那么這段程序是應(yīng)該放到所有路由的最前面的,也就是說(shuō)這段程序是所有路由要經(jīng)過(guò)的一段程序,也就是我們所說(shuō)的中間件。好的,廢話不多說(shuō),上代碼
const fs = require('fs') const log = (req,res) => { const ip = req.ip, route = req.route.path const log = `ip:${ip} path:${route}` fs.writeFileSync(__dirname + '/log',log) }
比如現(xiàn)在我有一個(gè)log函數(shù),它專門(mén)用來(lái)記錄訪問(wèn)日志的。如何所有的都一起執(zhí)行了,我們加一段這樣的代碼
app.use(log)
它加在所有代碼的最上面,但是不是加上就完事了,還必須在log函數(shù)里面再加一段代碼,不然當(dāng)程序執(zhí)行到里面之后就出不去了,什么代碼了。我們重寫(xiě)log函數(shù)
const log = (req,res,next) => { const ip = req.ip, route = req.route.path const log = `ip:${ip} path:${route}` fs.writeFileSync(__dirname + '/log',log) next() }
大家有沒(méi)有看見(jiàn)那個(gè)next,它有什么作用了。前面我們提到,它其實(shí)就是一個(gè)過(guò)渡者,主要的作用其實(shí)就是經(jīng)過(guò)之后,要繼續(xù)往下面執(zhí)行,還是就此終止返回結(jié)果。
說(shuō)的簡(jiǎn)單一點(diǎn),就是我們一個(gè)http請(qǐng)求,到達(dá)我們的node服務(wù)器之后,要經(jīng)歷的過(guò)程,而每經(jīng)過(guò)一個(gè)程序塊,就是個(gè)中間件,每一個(gè)中間件只要有next就會(huì)傳遞到下一個(gè)中間件里面,直到服務(wù)器res響應(yīng)結(jié)果,整個(gè)路由就此結(jié)束。
我們整合一下代碼。并且精簡(jiǎn)一下,也跑一遍程序
const express = require('express') const app = express() const log = (req,res,next) => { const ip = req.ip, route = req.route.path const log = `ip:${ip} path:${route}` fs.writeFileSync(__dirname + '/log',log) next() } app.use(log)//任何請(qǐng)求都會(huì)經(jīng)過(guò)這個(gè)log中間件 app.get('/', (req, res) => { console.log(req.route.stack) res.send('這是一個(gè)根路由!') }) app.get('/router1', (req, res) => { res.send('這是一個(gè)router1路由!') }) app.get('/router2', (req, res) => { res.send('這是一個(gè)router2路由!') }) app.listen(3000, () => { console.log('app listening on port 3000!') })
GET '/router2' //打印日志,并且返回結(jié)果
這就是一個(gè)簡(jiǎn)單的中間件解釋了。大家也可以回去看看你原來(lái)寫(xiě)過(guò)的代碼,是否對(duì)之前的use這個(gè)玩意有點(diǎn)啟發(fā)了?
感謝各位的閱讀!關(guān)于“express.js框架中間件的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。