日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁(yè) > 科技  > 軟件

花 15 分鐘把 Express.js 搞明白,全棧沒(méi)有那么難

來(lái)源: 責(zé)編: 時(shí)間:2024-01-16 17:32:15 231觀(guān)看
導(dǎo)讀大家好,我是楊成功。Express 是老牌的 Node.js 框架,以簡(jiǎn)單和輕量著稱(chēng),幾行代碼就可以啟動(dòng)一個(gè) HTTP 服務(wù)器。市面上主流的 Node.js 框架,如 Egg.js、Nest.js 等都與 Express 息息相關(guān)。Express 框架使用標(biāo)準(zhǔn) Node.js 語(yǔ)

Kjj28資訊網(wǎng)——每日最新資訊28at.com

大家好,我是楊成功。Kjj28資訊網(wǎng)——每日最新資訊28at.com

Express 是老牌的 Node.js 框架,以簡(jiǎn)單和輕量著稱(chēng),幾行代碼就可以啟動(dòng)一個(gè) HTTP 服務(wù)器。市面上主流的 Node.js 框架,如 Egg.js、Nest.js 等都與 Express 息息相關(guān)。Kjj28資訊網(wǎng)——每日最新資訊28at.com

Express 框架使用標(biāo)準(zhǔn) Node.js 語(yǔ)法,主要由以下 3 個(gè)核心部分組成:Kjj28資訊網(wǎng)——每日最新資訊28at.com

  • 路由。
  • 中間件。
  • 錯(cuò)誤處理。

認(rèn)識(shí)基本結(jié)構(gòu)

Express 的基本結(jié)構(gòu)很簡(jiǎn)單,只需要三行代碼,應(yīng)用就可以運(yùn)行起來(lái)。Kjj28資訊網(wǎng)——每日最新資訊28at.com

const express = require('express')const app = express()app.listen(9000, () => console.log('啟動(dòng)成功'))

假設(shè)上述代碼寫(xiě)在 index.js 中,我們啟動(dòng)該應(yīng)用使用命令 node ./index.js,控制臺(tái)會(huì)輸出“啟動(dòng)成功”。Kjj28資訊網(wǎng)——每日最新資訊28at.com

為了方便,我們也可以在 package.json 中創(chuàng)建快捷命令,如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

// package.json{  "scripts": {    "start": "node ./index.js"  }}

那么現(xiàn)在啟動(dòng)應(yīng)用就可以用 npm run start 命令。Kjj28資訊網(wǎng)——每日最新資訊28at.com

不過(guò)這種方式在本地運(yùn)行項(xiàng)目時(shí)會(huì)有一個(gè)弊端,就是修改文件后不會(huì)立即生效,需要重新啟動(dòng)。為了提高效率,一般會(huì)使用一個(gè)名為 PM2 的模塊啟動(dòng) Node.js 應(yīng)用。Kjj28資訊網(wǎng)——每日最新資訊28at.com

首先全局安裝 pm2:Kjj28資訊網(wǎng)——每日最新資訊28at.com

$ npm install -g pm2

安裝后在項(xiàng)目目錄下創(chuàng)建啟動(dòng)配置文件 ecosystem.config.js,代碼如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

module.exports = {  apps: [    {      name: 'first-api',      script: './index.js',    },  ],}

然后在項(xiàng)目目錄下執(zhí)行以下命令就可以啟動(dòng)項(xiàng)目了:Kjj28資訊網(wǎng)——每日最新資訊28at.com

$ pm2 start --watch

圖片Kjj28資訊網(wǎng)——每日最新資訊28at.com

上圖中的 0 就是啟動(dòng)應(yīng)用的 ID,下面會(huì)用到。Kjj28資訊網(wǎng)——每日最新資訊28at.com

PM2 常用大命令如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

  • pm2 start:?jiǎn)?dòng)應(yīng)用,--watch 表示監(jiān)聽(tīng)文件修改自動(dòng)重啟。
  • pm2 list:查看已啟動(dòng)的應(yīng)用列表。
  • pm2 logs <id>:查看日志輸出。
  • pm2 delete <id>:刪除指定應(yīng)用。

應(yīng)用啟動(dòng)后監(jiān)聽(tīng) 9000 端口,但訪(fǎng)問(wèn) “http://localhost:9000” 卻沒(méi)有反應(yīng),請(qǐng)求被掛起,這是因?yàn)闆](méi)有設(shè)置如何處理請(qǐng)求。Kjj28資訊網(wǎng)——每日最新資訊28at.com

Express 中通過(guò)定義路由來(lái)處理請(qǐng)求。Kjj28資訊網(wǎng)——每日最新資訊28at.com

使用路由創(chuàng)建 API 接口

路由用于定義如何處理請(qǐng)求,定義方式采用以下結(jié)構(gòu):Kjj28資訊網(wǎng)——每日最新資訊28at.com

app.METHOD(PATH, HANDLER)

其中 app 表示 Express 的實(shí)例,其余的三個(gè)部分都屬于路由配置,表示的含義如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

  • METHOD:路由方法。
  • PATH:路由地址。
  • HANDLER:路由處理函數(shù)。

比如示例代碼中的路由是這樣子:Kjj28資訊網(wǎng)——每日最新資訊28at.com

app.get('/', (req, res) => {  res.send('Hello World')})

使用app.get()定義了一個(gè) GET 請(qǐng)求的路由,第一個(gè)參數(shù) “/” 為路由地址,第二個(gè)參數(shù)為路由處理函數(shù),是一個(gè)回調(diào)函數(shù),該函數(shù)接受兩個(gè)參數(shù)分別表示請(qǐng)求和響應(yīng)。Kjj28資訊網(wǎng)——每日最新資訊28at.com

當(dāng)路由方法和路由地址匹配到用戶(hù)請(qǐng)求時(shí),路由處理函數(shù)就會(huì)執(zhí)行。Kjj28資訊網(wǎng)——每日最新資訊28at.com

路由方法根據(jù)基本 API 規(guī)則支持五種,分別如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

  • app.get():GET 請(qǐng)求。
  • app.post():POST 請(qǐng)求。
  • app.put():PUT 請(qǐng)求。
  • app.delete():DELETE 請(qǐng)求。
  • app.all():匹配所有請(qǐng)求。

以上五個(gè)方法的參數(shù)都與示例路由一致。定義好路由后,我們的主要任務(wù)是在路由處理函數(shù)中編寫(xiě)業(yè)務(wù)代碼,一般會(huì)包括接收請(qǐng)求參數(shù)、返回接口響應(yīng),這里要用到路由處理函數(shù)的兩個(gè)參數(shù)。Kjj28資訊網(wǎng)——每日最新資訊28at.com

請(qǐng)求對(duì)象

路由處理函數(shù)的第一個(gè)參數(shù)表示請(qǐng)求對(duì)象,包含客戶(hù)端請(qǐng)求攜帶的相關(guān)數(shù)據(jù),常用的屬性如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

  • req.query:URL 附加參數(shù)。
  • req.body:請(qǐng)求體參數(shù)。
  • req.method:請(qǐng)求方法。
  • req.headers:請(qǐng)求頭對(duì)象。
  • req.params:URL 地址參數(shù)。

現(xiàn)在我們定義一個(gè)路由,將請(qǐng)求對(duì)象的這幾個(gè)屬性返回,看一下它們的值是什么:Kjj28資訊網(wǎng)——每日最新資訊28at.com

app.post('/first/:id', (req, res) => {  let { method, query, body, params, headers } = req  res.send({ method, query, body, params, headers })})

在 Postman 中請(qǐng)求地址 “http://localhost:9000/first/8?tag=test” 并傳入請(qǐng)求體參數(shù) {data: "xxx"},請(qǐng)求結(jié)果如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

圖片Kjj28資訊網(wǎng)——每日最新資訊28at.com

對(duì)照請(qǐng)求參數(shù)和返回結(jié)果,可以發(fā)現(xiàn)路由地址中的 :id 占位符解析后被放到 “req.params” 對(duì)象下。地址參數(shù) ?tag=test 解析后被放到 “req.query” 對(duì)象下。Kjj28資訊網(wǎng)——每日最新資訊28at.com

但是有一個(gè)問(wèn)題:請(qǐng)求體沒(méi)有被解析出來(lái)。Kjj28資訊網(wǎng)——每日最新資訊28at.com

這是因?yàn)檎?qǐng)求體是按照流處理的,無(wú)法直接獲取到,我們需要一個(gè)第三方工具包協(xié)助。首先安裝如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

$ yarn add body-parser

然后在 index.js 中引入并加載:Kjj28資訊網(wǎng)——每日最新資訊28at.com

const bodyParser = require('body-parser')app.use(bodyParser.json())

現(xiàn)在重新請(qǐng)求,接可以看到 req.body 的返回結(jié)果了:Kjj28資訊網(wǎng)——每日最新資訊28at.com

圖片Kjj28資訊網(wǎng)——每日最新資訊28at.com

響應(yīng)對(duì)象

路由處理函數(shù)的第二個(gè)參數(shù)表示響應(yīng)對(duì)象,用于向客戶(hù)端返回結(jié)果,也就是定義接口的返回值。路由處理函數(shù)中必須設(shè)置響應(yīng),否則客戶(hù)端請(qǐng)求會(huì)一直處于掛起狀態(tài),無(wú)返回值。Kjj28資訊網(wǎng)——每日最新資訊28at.com

常用的響應(yīng)方法有以下三種,用于返回不同類(lèi)型的數(shù)據(jù):Kjj28資訊網(wǎng)——每日最新資訊28at.com

  • res.json():發(fā)送 JSON 響應(yīng)。
  • res.render():發(fā)送視圖響應(yīng)(HTML)。
  • res.send():發(fā)送各種類(lèi)型的響應(yīng)。

我們統(tǒng)一使用 res.send() 方法響應(yīng)數(shù)據(jù)。一般在響應(yīng)前還可以通過(guò) res.status() 方法設(shè)置 HTTP 狀態(tài)碼,示例如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

res.send('哈哈') // 狀態(tài)碼:200,返回值:"哈哈"res.status(201).send({  msg: 'created',}) // 狀態(tài)碼:201,返回值:{msg:"created"}res.status(401).send('請(qǐng)登錄') // 狀態(tài)碼:401,返回值:"請(qǐng)登錄"

發(fā)送響應(yīng)時(shí)也常常會(huì)遇到問(wèn)題,以下兩條原則請(qǐng)牢記,避免踩坑:Kjj28資訊網(wǎng)——每日最新資訊28at.com

  • 一個(gè)路由處理函數(shù)中只能響應(yīng)一次,不能重復(fù)響應(yīng)。
  • res.send() 不能直接返回?cái)?shù)字。

分組路由

使用 app 實(shí)例注冊(cè)路由固然方便,但是如果定義的路由很多,都注冊(cè)在 app 實(shí)例下很可能會(huì)帶來(lái)全局污染,這與全局變量一個(gè)道理。為了應(yīng)用的健壯性,我們應(yīng)該將路由分組。Kjj28資訊網(wǎng)——每日最新資訊28at.com

Express 提供了 Router 類(lèi)來(lái)創(chuàng)建模塊化的路由程序,它像一個(gè)微應(yīng)用,可以隨時(shí)被 app 實(shí)例掛載。這樣就可以把一組路由保存在一個(gè)單獨(dú)的文件中,需要時(shí)加載,從而實(shí)現(xiàn)路由分組。Kjj28資訊網(wǎng)——每日最新資訊28at.com

創(chuàng)建一個(gè) router 文件夾用于保存路由文件,然后創(chuàng)建 router/test.js 文件,在文件中呢寫(xiě)入路由代碼,如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

// router/test.jsvar express = require('express')var router = express.Router()router.post('/info', (req, res) => {  res.send('TEST 路由組')})module.exports = router

這樣一個(gè)基本的路由模塊就寫(xiě)好了,如果讓其生效,需要在主程序中加載該模塊:Kjj28資訊網(wǎng)——每日最新資訊28at.com

const testRouter = require('./router/test.js')app.use('/test', testRouter)

上述代碼表示請(qǐng)求 “/test” 時(shí)加載路由模塊,訪(fǎng)問(wèn)某個(gè)路由時(shí)使用該路徑拼接路由地址,像下面這樣:Kjj28資訊網(wǎng)——每日最新資訊28at.com

http://localhost:9000/test/info# 返回 "TEST 路由組"

為了開(kāi)發(fā)規(guī)范,我們統(tǒng)一把路由定義為路由模塊,而不直接在 app 下注冊(cè)。Kjj28資訊網(wǎng)——每日最新資訊28at.com

理解中間件,搞懂框架原理

Express 應(yīng)用是由一系列中間件構(gòu)成的。中間件同樣是一個(gè)聽(tīng)著很玄乎的詞兒,但它的本質(zhì)就是一個(gè)函數(shù)。我們看一個(gè)中間件函數(shù)的代碼示例:Kjj28資訊網(wǎng)——每日最新資訊28at.com

var myLogger = function (req, res, next) {  console.log('LOGGED')  next()}

中間件與普通函數(shù)的區(qū)別就是它有三個(gè)參數(shù),分別表示請(qǐng)求對(duì)象(req),響應(yīng)對(duì)象(res)和一個(gè) next() 函數(shù) ——— 也許你發(fā)現(xiàn)了,路由處理函數(shù)也是這個(gè)結(jié)構(gòu)。Kjj28資訊網(wǎng)——每日最新資訊28at.com

沒(méi)錯(cuò),路由處理函數(shù)本身就是一個(gè)中間件。Kjj28資訊網(wǎng)——每日最新資訊28at.com

將中間件掛載到應(yīng)用上,使用 app.use() 方法:Kjj28資訊網(wǎng)——每日最新資訊28at.com

app.use(myLogger)

看到這里你又會(huì)發(fā)現(xiàn),請(qǐng)求體解析包 body-parser 也是這么掛載的,因?yàn)樵摪彩且粋€(gè)中間件。Kjj28資訊網(wǎng)——每日最新資訊28at.com

直接用 app.use() 掛載的中間件在收到任意請(qǐng)求時(shí)都會(huì)執(zhí)行。如果要限定執(zhí)行條件,可以添加一個(gè)路徑匹配,如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

app.use('/test/*', myLogger)

這樣,只有以 /test 開(kāi)頭的請(qǐng)求才會(huì)執(zhí)行 myLogger 中間件,這看起來(lái)與路由注冊(cè)很相似。其實(shí)注冊(cè)路由正是這種中間件掛載方式的快捷寫(xiě)法,只不過(guò)多了一個(gè)請(qǐng)求方法的限制。Kjj28資訊網(wǎng)——每日最新資訊28at.com

Express 應(yīng)用中一切皆中間件,如果匹配到多個(gè)中間件會(huì)按照順序依次調(diào)用。此時(shí) next() 函數(shù)就能派上用場(chǎng)了,他的作用是進(jìn)入下一個(gè)中間件。Kjj28資訊網(wǎng)——每日最新資訊28at.com

比如代碼中的 myLogger 中間件,將它掛載到路由之前,那么每次請(qǐng)求首先會(huì)打印出 “LOGGED”,然后再進(jìn)入路由處理函數(shù)。Kjj28資訊網(wǎng)——每日最新資訊28at.com

如果 myLogger 中間件中沒(méi)有調(diào)用 next() 函數(shù),請(qǐng)求就會(huì)被堵在這里,無(wú)法進(jìn)入路由處理函數(shù),此時(shí)請(qǐng)求會(huì)被掛起。Kjj28資訊網(wǎng)——每日最新資訊28at.com

統(tǒng)一錯(cuò)誤處理,提升健壯性

既然一切皆中間件,那么錯(cuò)誤處理也是一個(gè)中間件。錯(cuò)誤處理函數(shù)與其他的中間件函數(shù)稍有不同,它多了一個(gè) err 參數(shù),如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

app.use((err, req, res, next) => {  console.error(err.stack)  res.status(500).send('服務(wù)器出錯(cuò)了!')})

err 參數(shù)表示錯(cuò)誤信息,當(dāng)發(fā)生錯(cuò)誤時(shí)進(jìn)入該中間件,此時(shí)要設(shè)置 HTTP 狀態(tài)碼為 500,并根據(jù)錯(cuò)誤信息為客戶(hù)端返回錯(cuò)誤響應(yīng)。Kjj28資訊網(wǎng)——每日最新資訊28at.com

錯(cuò)誤處理中間件是一個(gè)兜底中間件,請(qǐng)確保它定義在所有中間件之后,是應(yīng)用中的最后一個(gè)中間件。Kjj28資訊網(wǎng)——每日最新資訊28at.com

請(qǐng)求進(jìn)入錯(cuò)誤中間件,說(shuō)明前面的所有中間件都沒(méi)有匹配到。但是如果客戶(hù)端請(qǐng)求地址寫(xiě)錯(cuò)而進(jìn)入錯(cuò)誤處理中間件,此時(shí)返回 500 錯(cuò)誤顯然不合理,應(yīng)該是 404 資源未找到。Kjj28資訊網(wǎng)——每日最新資訊28at.com

所以在錯(cuò)誤處理中間件前,還應(yīng)該定義一個(gè) 404 中間件。該中間件要在所有路由之后,錯(cuò)誤處理之前,是應(yīng)用的倒數(shù)第二個(gè)中間件,代碼如下:Kjj28資訊網(wǎng)——每日最新資訊28at.com

app.use((req, res, next) => {  res.status(404).send('Not Found')})

好了,現(xiàn)在我們的應(yīng)用就健壯多了。Kjj28資訊網(wǎng)——每日最新資訊28at.com

總結(jié)

本文列舉了 Express 框架的核心,并舉例如何應(yīng)用,整體并沒(méi)有那么難。掌握這部分知識(shí),可以快速擁 API 開(kāi)發(fā)的思維。Kjj28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-62788-0.html花 15 分鐘把 Express.js 搞明白,全棧沒(méi)有那么難

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 提高代碼效率的六個(gè)Python內(nèi)存優(yōu)化技巧

下一篇: 總結(jié)了十個(gè)Vue3超級(jí)實(shí)用但是很冷門(mén)的API

標(biāo)簽:
  • 熱門(mén)焦點(diǎn)
Top 主站蜘蛛池模板: 锡林浩特市| 保定市| 上高县| 北辰区| 镇安县| 城步| 忻城县| 若尔盖县| 永吉县| 龙南县| 师宗县| 南靖县| 惠水县| 正定县| 镇雄县| 古浪县| 顺平县| 鄂托克前旗| 洱源县| 若尔盖县| 乳源| 普格县| 东方市| 云浮市| 年辖:市辖区| 鄂尔多斯市| 辽阳县| 洛南县| 吉首市| 闸北区| 海伦市| 新闻| 安塞县| 洞口县| 游戏| 慈利县| 麻栗坡县| 嘉义县| 应城市| 吴旗县| 庄浪县|