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

當前位置:首頁 > 科技  > 軟件

花 15 分鐘把 Express.js 搞明白,全棧沒有那么難

來源: 責編: 時間:2024-01-16 17:32:15 201觀看
導讀大家好,我是楊成功。Express 是老牌的 Node.js 框架,以簡單和輕量著稱,幾行代碼就可以啟動一個 HTTP 服務器。市面上主流的 Node.js 框架,如 Egg.js、Nest.js 等都與 Express 息息相關。Express 框架使用標準 Node.js 語

9AB28資訊網——每日最新資訊28at.com

大家好,我是楊成功。9AB28資訊網——每日最新資訊28at.com

Express 是老牌的 Node.js 框架,以簡單和輕量著稱,幾行代碼就可以啟動一個 HTTP 服務器。市面上主流的 Node.js 框架,如 Egg.js、Nest.js 等都與 Express 息息相關。9AB28資訊網——每日最新資訊28at.com

Express 框架使用標準 Node.js 語法,主要由以下 3 個核心部分組成:9AB28資訊網——每日最新資訊28at.com

  • 路由。
  • 中間件。
  • 錯誤處理。

認識基本結構

Express 的基本結構很簡單,只需要三行代碼,應用就可以運行起來。9AB28資訊網——每日最新資訊28at.com

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

假設上述代碼寫在 index.js 中,我們啟動該應用使用命令 node ./index.js,控制臺會輸出“啟動成功”。9AB28資訊網——每日最新資訊28at.com

為了方便,我們也可以在 package.json 中創建快捷命令,如下:9AB28資訊網——每日最新資訊28at.com

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

那么現在啟動應用就可以用 npm run start 命令。9AB28資訊網——每日最新資訊28at.com

不過這種方式在本地運行項目時會有一個弊端,就是修改文件后不會立即生效,需要重新啟動。為了提高效率,一般會使用一個名為 PM2 的模塊啟動 Node.js 應用。9AB28資訊網——每日最新資訊28at.com

首先全局安裝 pm2:9AB28資訊網——每日最新資訊28at.com

$ npm install -g pm2

安裝后在項目目錄下創建啟動配置文件 ecosystem.config.js,代碼如下:9AB28資訊網——每日最新資訊28at.com

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

然后在項目目錄下執行以下命令就可以啟動項目了:9AB28資訊網——每日最新資訊28at.com

$ pm2 start --watch

圖片9AB28資訊網——每日最新資訊28at.com

上圖中的 0 就是啟動應用的 ID,下面會用到。9AB28資訊網——每日最新資訊28at.com

PM2 常用大命令如下:9AB28資訊網——每日最新資訊28at.com

  • pm2 start:啟動應用,--watch 表示監聽文件修改自動重啟。
  • pm2 list:查看已啟動的應用列表。
  • pm2 logs <id>:查看日志輸出。
  • pm2 delete <id>:刪除指定應用。

應用啟動后監聽 9000 端口,但訪問 “http://localhost:9000” 卻沒有反應,請求被掛起,這是因為沒有設置如何處理請求。9AB28資訊網——每日最新資訊28at.com

Express 中通過定義路由來處理請求。9AB28資訊網——每日最新資訊28at.com

使用路由創建 API 接口

路由用于定義如何處理請求,定義方式采用以下結構:9AB28資訊網——每日最新資訊28at.com

app.METHOD(PATH, HANDLER)

其中 app 表示 Express 的實例,其余的三個部分都屬于路由配置,表示的含義如下:9AB28資訊網——每日最新資訊28at.com

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

比如示例代碼中的路由是這樣子:9AB28資訊網——每日最新資訊28at.com

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

使用app.get()定義了一個 GET 請求的路由,第一個參數 “/” 為路由地址,第二個參數為路由處理函數,是一個回調函數,該函數接受兩個參數分別表示請求和響應。9AB28資訊網——每日最新資訊28at.com

當路由方法和路由地址匹配到用戶請求時,路由處理函數就會執行。9AB28資訊網——每日最新資訊28at.com

路由方法根據基本 API 規則支持五種,分別如下:9AB28資訊網——每日最新資訊28at.com

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

以上五個方法的參數都與示例路由一致。定義好路由后,我們的主要任務是在路由處理函數中編寫業務代碼,一般會包括接收請求參數、返回接口響應,這里要用到路由處理函數的兩個參數。9AB28資訊網——每日最新資訊28at.com

請求對象

路由處理函數的第一個參數表示請求對象,包含客戶端請求攜帶的相關數據,常用的屬性如下:9AB28資訊網——每日最新資訊28at.com

  • req.query:URL 附加參數。
  • req.body:請求體參數。
  • req.method:請求方法。
  • req.headers:請求頭對象。
  • req.params:URL 地址參數。

現在我們定義一個路由,將請求對象的這幾個屬性返回,看一下它們的值是什么:9AB28資訊網——每日最新資訊28at.com

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

在 Postman 中請求地址 “http://localhost:9000/first/8?tag=test” 并傳入請求體參數 {data: "xxx"},請求結果如下:9AB28資訊網——每日最新資訊28at.com

圖片9AB28資訊網——每日最新資訊28at.com

對照請求參數和返回結果,可以發現路由地址中的 :id 占位符解析后被放到 “req.params” 對象下。地址參數 ?tag=test 解析后被放到 “req.query” 對象下。9AB28資訊網——每日最新資訊28at.com

但是有一個問題:請求體沒有被解析出來。9AB28資訊網——每日最新資訊28at.com

這是因為請求體是按照流處理的,無法直接獲取到,我們需要一個第三方工具包協助。首先安裝如下:9AB28資訊網——每日最新資訊28at.com

$ yarn add body-parser

然后在 index.js 中引入并加載:9AB28資訊網——每日最新資訊28at.com

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

現在重新請求,接可以看到 req.body 的返回結果了:9AB28資訊網——每日最新資訊28at.com

圖片9AB28資訊網——每日最新資訊28at.com

響應對象

路由處理函數的第二個參數表示響應對象,用于向客戶端返回結果,也就是定義接口的返回值。路由處理函數中必須設置響應,否則客戶端請求會一直處于掛起狀態,無返回值。9AB28資訊網——每日最新資訊28at.com

常用的響應方法有以下三種,用于返回不同類型的數據:9AB28資訊網——每日最新資訊28at.com

  • res.json():發送 JSON 響應。
  • res.render():發送視圖響應(HTML)。
  • res.send():發送各種類型的響應。

我們統一使用 res.send() 方法響應數據。一般在響應前還可以通過 res.status() 方法設置 HTTP 狀態碼,示例如下:9AB28資訊網——每日最新資訊28at.com

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

發送響應時也常常會遇到問題,以下兩條原則請牢記,避免踩坑:9AB28資訊網——每日最新資訊28at.com

  • 一個路由處理函數中只能響應一次,不能重復響應。
  • res.send() 不能直接返回數字。

分組路由

使用 app 實例注冊路由固然方便,但是如果定義的路由很多,都注冊在 app 實例下很可能會帶來全局污染,這與全局變量一個道理。為了應用的健壯性,我們應該將路由分組。9AB28資訊網——每日最新資訊28at.com

Express 提供了 Router 類來創建模塊化的路由程序,它像一個微應用,可以隨時被 app 實例掛載。這樣就可以把一組路由保存在一個單獨的文件中,需要時加載,從而實現路由分組。9AB28資訊網——每日最新資訊28at.com

創建一個 router 文件夾用于保存路由文件,然后創建 router/test.js 文件,在文件中呢寫入路由代碼,如下:9AB28資訊網——每日最新資訊28at.com

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

這樣一個基本的路由模塊就寫好了,如果讓其生效,需要在主程序中加載該模塊:9AB28資訊網——每日最新資訊28at.com

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

上述代碼表示請求 “/test” 時加載路由模塊,訪問某個路由時使用該路徑拼接路由地址,像下面這樣:9AB28資訊網——每日最新資訊28at.com

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

為了開發規范,我們統一把路由定義為路由模塊,而不直接在 app 下注冊。9AB28資訊網——每日最新資訊28at.com

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

Express 應用是由一系列中間件構成的。中間件同樣是一個聽著很玄乎的詞兒,但它的本質就是一個函數。我們看一個中間件函數的代碼示例:9AB28資訊網——每日最新資訊28at.com

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

中間件與普通函數的區別就是它有三個參數,分別表示請求對象(req),響應對象(res)和一個 next() 函數 ——— 也許你發現了,路由處理函數也是這個結構。9AB28資訊網——每日最新資訊28at.com

沒錯,路由處理函數本身就是一個中間件。9AB28資訊網——每日最新資訊28at.com

將中間件掛載到應用上,使用 app.use() 方法:9AB28資訊網——每日最新資訊28at.com

app.use(myLogger)

看到這里你又會發現,請求體解析包 body-parser 也是這么掛載的,因為該包也是一個中間件。9AB28資訊網——每日最新資訊28at.com

直接用 app.use() 掛載的中間件在收到任意請求時都會執行。如果要限定執行條件,可以添加一個路徑匹配,如下:9AB28資訊網——每日最新資訊28at.com

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

這樣,只有以 /test 開頭的請求才會執行 myLogger 中間件,這看起來與路由注冊很相似。其實注冊路由正是這種中間件掛載方式的快捷寫法,只不過多了一個請求方法的限制。9AB28資訊網——每日最新資訊28at.com

Express 應用中一切皆中間件,如果匹配到多個中間件會按照順序依次調用。此時 next() 函數就能派上用場了,他的作用是進入下一個中間件。9AB28資訊網——每日最新資訊28at.com

比如代碼中的 myLogger 中間件,將它掛載到路由之前,那么每次請求首先會打印出 “LOGGED”,然后再進入路由處理函數。9AB28資訊網——每日最新資訊28at.com

如果 myLogger 中間件中沒有調用 next() 函數,請求就會被堵在這里,無法進入路由處理函數,此時請求會被掛起。9AB28資訊網——每日最新資訊28at.com

統一錯誤處理,提升健壯性

既然一切皆中間件,那么錯誤處理也是一個中間件。錯誤處理函數與其他的中間件函數稍有不同,它多了一個 err 參數,如下:9AB28資訊網——每日最新資訊28at.com

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

err 參數表示錯誤信息,當發生錯誤時進入該中間件,此時要設置 HTTP 狀態碼為 500,并根據錯誤信息為客戶端返回錯誤響應。9AB28資訊網——每日最新資訊28at.com

錯誤處理中間件是一個兜底中間件,請確保它定義在所有中間件之后,是應用中的最后一個中間件。9AB28資訊網——每日最新資訊28at.com

請求進入錯誤中間件,說明前面的所有中間件都沒有匹配到。但是如果客戶端請求地址寫錯而進入錯誤處理中間件,此時返回 500 錯誤顯然不合理,應該是 404 資源未找到。9AB28資訊網——每日最新資訊28at.com

所以在錯誤處理中間件前,還應該定義一個 404 中間件。該中間件要在所有路由之后,錯誤處理之前,是應用的倒數第二個中間件,代碼如下:9AB28資訊網——每日最新資訊28at.com

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

好了,現在我們的應用就健壯多了。9AB28資訊網——每日最新資訊28at.com

總結

本文列舉了 Express 框架的核心,并舉例如何應用,整體并沒有那么難。掌握這部分知識,可以快速擁 API 開發的思維。9AB28資訊網——每日最新資訊28at.com

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

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 提高代碼效率的六個Python內存優化技巧

下一篇: 總結了十個Vue3超級實用但是很冷門的API

標簽:
  • 熱門焦點
  • 掘力計劃第 20 期:Flutter 混合開發的混亂之治

    在掘力計劃系列活動第20場,《Flutter 開發實戰詳解》作者,掘金優秀作者,Github GSY 系列目負責人戀貓的小郭分享了Flutter 混合開發的混亂之治。Flutter 基于自研的 Skia 引擎
  • 之家push系統迭代之路

    前言在這個信息爆炸的互聯網時代,能夠及時準確獲取信息是當今社會要解決的關鍵問題之一。隨著之家用戶體量和內容規模的不斷增大,傳統的靠"主動拉"獲取信息的方式已不能滿足用
  • 三言兩語說透柯里化和反柯里化

    JavaScript中的柯里化(Currying)和反柯里化(Uncurrying)是兩種很有用的技術,可以幫助我們寫出更加優雅、泛用的函數。本文將首先介紹柯里化和反柯里化的概念、實現原理和應用
  • 一文掌握 Golang 模糊測試(Fuzz Testing)

    模糊測試(Fuzz Testing)模糊測試(Fuzz Testing)是通過向目標系統提供非預期的輸入并監視異常結果來發現軟件漏洞的方法。可以用來發現應用程序、操作系統和網絡協議等中的漏洞或
  • JVM優化:實戰OutOfMemoryError異常

    一、Java堆溢出堆內存中主要存放對象、數組等,只要不斷地創建這些對象,并且保證 GC Roots 到對象之間有可達路徑來避免垃 圾收集回收機制清除這些對象,當這些對象所占空間超過
  • 消費結構調整丨巨頭低價博弈,拼多多還卷得動嗎?

    來源:征探財經作者:陳香羽隨著流量紅利的退潮,電商的存量博弈越來越明顯。曾經主攻中高端與品質的淘寶天貓、京東重拾&ldquo;低價&rdquo;口號。而過去與他們錯位競爭的拼多多,靠
  • 小米MIX Fold 3配置細節曝光:搭載領先版驍龍8 Gen2+罕見5倍長焦

    這段時間以來,包括三星、一加、榮耀等等有不少品牌旗下的最新折疊屏旗艦都得到了不少爆料,而小米新一代折疊屏旗艦——小米MIX Fold 3此前也屢屢被傳
  • iQOO Neo8 Pro評測:旗艦雙芯加持 最強性能游戲旗艦

    【Techweb評測】去年10月,iQOO推出了一款Neo7手機,該機搭載了聯發科天璣9000+,配備獨顯芯片Pro+,帶來了同價位段最佳的游戲體驗,一經上市便受到了諸多用
  • OPPO K11搭載高性能石墨散熱系統:旗艦同款 性能涼爽釋放

    日前OPPO官方宣布,將于7月25日14:30舉辦新品發布會,屆時全新的OPPO K11將正式與大家見面,將主打旗艦影像,和同檔位競品相比,其最大的賣點就是將配備索尼
Top 主站蜘蛛池模板: 和平区| 贵南县| 咸阳市| 邢台县| 确山县| 浏阳市| 五常市| 广丰县| 黑龙江省| 稷山县| 尼木县| 依兰县| 博湖县| 合肥市| 天水市| 珠海市| 调兵山市| 黄冈市| 海原县| 儋州市| 镇巴县| 田东县| 霍城县| 阜新市| 金秀| 枣强县| 通榆县| 武清区| 邢台市| 隆子县| 荔波县| 涟源市| 赣榆县| 肃宁县| 哈巴河县| 克东县| 柳江县| 定远县| 行唐县| 建宁县| 遵化市|