第五部分:第五節 - Express 路由與中間件進階:廚房的分工與異常處理

隨著你的 Express 應用變得越來越大,所有的路由和中間件都寫在一個文件里會變得難以管理。這時候就需要將代碼進行拆分和組織。此外,一個健壯的后端應用必須能夠優雅地處理錯誤和一些常見的 Web 開發問題,比如跨域。

路由模塊化 (express.Router):

express.Router 是 Express 提供的一個迷你應用,它有自己的中間件和路由。你可以把處理某個特定資源的路由(比如所有用戶相關的路由)放到一個單獨的文件中,然后像中間件一樣將其掛載到主應用上。這就像在廚房里為不同的菜品(資源)設立了專門的操作臺(路由文件),每個操作臺有自己的工作流程,但它們最終都屬于整個廚房(主應用)。

創建一個新的文件,比如 routes/users.js

// routes/users.js
const express = require('express');
const router = express.Router(); // 創建一個 Router 實例// 這里可以定義用戶相關的中間件,只應用于本路由文件中的路由
// router.use((req, res, next) => { console.log('用戶路由中間件'); next(); });// 定義用戶相關的路由
router.get('/', (req, res) => {// 處理獲取所有用戶的邏輯res.send('獲取所有用戶');
});router.get('/:userId', (req, res) => {const userId = req.params.userId;// 處理獲取單個用戶的邏輯res.send(`獲取用戶 ID: ${userId}`);
});router.post('/', (req, res) => {// 處理創建用戶的邏輯res.send('創建新用戶');
});// ... 其他用戶相關的路由 (PUT, DELETE)module.exports = router; // 導出 router 實例 (CommonJS 方式)// 如果使用 ES Modules:
// export default router;

在你的主應用文件 app.js 中導入并使用這個路由模塊:

// app.js
const express = require('express');
const app = express();
const port = 3000;// 導入用戶路由模塊
const usersRouter = require('./routes/users');
// const usersRouter from './routes/users.js'; // ES Modules// ... 其他中間件 (如 body-parser)// 將用戶路由模塊掛載到 /api/users 路徑下
app.use('/api/users', usersRouter);// ... 其他路由和中間件// 啟動服務器
app.listen(port, () => {console.log(`應用運行在 http://localhost:${port}`);
});// 現在訪問 /api/users 會由 usersRouter 處理
// 訪問 /api/users/123 會由 usersRouter.get('/:userId', ...) 處理

錯誤處理中間件:

在 Express 中,錯誤處理中間件有四個參數:(err, req, res, next)。當你在任何路由或普通中間件中調用 next(err) 并傳入一個錯誤對象時,Express 會跳過后續的路由和中間件,直接進入錯誤處理中間件。這就像廚房里某個環節出了問題(比如菜燒焦了),不用繼續整個流程,直接通知服務員(調用錯誤處理中間件)去處理這個“異常訂單”。

通常,你會在所有路由和普通中間件的后面定義錯誤處理中間件,以捕獲所有未被處理的錯誤。

// app.js (接著上面的代碼)// ... 所有路由和普通中間件 ...// 404 錯誤處理 (放在所有有效路由之后)
app.use((req, res, next) => {res.status(404).send("對不起,找不到該頁面!");
});// 錯誤處理中間件 (四個參數)
app.use((err, req, res, next) => {console.error("服務器端錯誤:", err.stack); // 打印錯誤堆棧到服務器控制臺res.status(500).send("服務器內部出錯!"); // 向客戶端發送 500 狀態碼和錯誤信息
});// 在路由中模擬錯誤
app.get('/error-test', (req, res, next) => {// 模擬一個錯誤const myError = new Error("這是一個測試錯誤");next(myError); // 將錯誤傳遞給錯誤處理中間件
});

常用的第三方中間件:

Express 的生態系統非常豐富,有很多優秀的第三方中間件可以方便地集成。

  • morgan (日志記錄): 記錄所有收到的 HTTP 請求信息,對于調試和監控非常有幫助。就像餐廳里的訂單記錄系統。
    • 安裝: npm install morgan
    • 使用: const morgan = require('morgan'); app.use(morgan('dev')); (dev 是預設的日志格式)
  • cors (跨域資源共享): 處理瀏覽器的同源策略限制,允許來自不同域的前端應用訪問你的后端 API。這就像允許來自不同地區的顧客在你的餐廳點餐。
    • 安裝: npm install cors
    • 使用: const cors = require('cors'); app.use(cors()); (允許所有跨域請求,也可以配置更精細的規則)
// app.js (接著上面的代碼)const morgan = require('morgan');
const cors = require('cors');// 使用 morgan 中間件記錄日志
app.use(morgan('dev'));// 使用 cors 中間件處理跨域
app.use(cors());// ... 其他路由和中間件 ...

小例子:模塊化路由和全局錯誤處理

請參考上面關于 express.Router 和錯誤處理中間件的代碼示例,將它們集成到一個完整的 Express 應用中。

小結: 使用 express.Router 可以將復雜的路由邏輯拆分到單獨的文件中,提高代碼的可組織性。錯誤處理中間件是捕獲和處理應用錯誤的統一方式。morgancors 是兩個非常常用的第三方中間件,分別用于日志記錄和跨域處理。

練習:

  1. 在你的 Express 項目中,為之前的“書籍”資源創建一個單獨的路由文件 (routes/books.js)。
  2. routes/books.js 中,使用 express.Router() 定義至少兩個路由(例如 GET / 和 GET /:bookId)。
  3. 在主應用文件 app.js 中導入 routes/books.js 并將其掛載到 /api/books 路徑下。
  4. 在主應用中添加一個 404 錯誤處理中間件(放在所有有效路由之后)。
  5. 在主應用中添加一個全局錯誤處理中間件,當接收到錯誤時,記錄錯誤到控制臺并向客戶端發送 500 狀態碼。
  6. 安裝并使用 morgan 中間件記錄所有請求日志。
  7. 安裝并使用 cors 中間件,允許所有來源的跨域請求。

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

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

相關文章

萌新聯賽第(三)場

C題 這道題用暴力去寫想都不要想,一定超時,于是我們需要優化,下面是思路過程: 如圖,本題只需找到x的因數個數和(n-x)的因數個數,這兩個相乘,得到的就是對于這個x來說組合的個數,且x…

【Android構建系統】如何在Camera Hal的Android.bp中選擇性引用某個模塊

背景描述 本篇文章是一個Android.bp中選擇性引用某個模塊的實例。 如果是Android.mk編譯時期,在編譯階段通過某個條件判斷是不是引用某個模塊A, 是比較好實現的。Android15使用Android.bp構建后,要想在Android.bp中通過自定義的一個變量或者條件實現選…

【OneNET】_01_使用微信小程序通過新版OneNET平臺獲取STM32設備信息并進行控制

【OneNET】_01_使用微信小程序通過新版OneNET平臺獲取STM32設備信息并進行控制 一、 前言1.1 OntNET硬件方面: STM32F103C8T6 ESP01S教程 1.2 微信小程序方面 二、STM32代碼部分修改三、微信小程序修改的部分四、小筆記(個人雜記)4.1 OneNETOneNET物聯網…

用 python 編寫的一個圖片自動分類小程序(三)

圖片自動分類識別小程序記錄 2025/5/18 0:38修改程序界面,增加一些功能 用 python 編寫的一個圖片自動識別分類小程序。 操作系統平臺:Microsoft Windows 11 編程語言和 IDE:python 3.10 Visual studio code 一:圖片自動分…

嵌入式硬件篇---SGP30 氣體傳感器

文章目錄 前言一、SGP30 氣體傳感器詳解(一)基本概述(二)工作原理傳感器結構檢測機制自校準功能(三)主要特性(四)應用場景智能家居空氣質量檢測儀汽車行業商業建筑二、TVOC 與 eCO2 的含義(一)TVOC(總揮發性有機化合物)定義危害健康標準(二)eCO2(等效二氧化碳)…

【原創】ubuntu22.04下載編譯AOSP 15

安裝依賴的庫,順便把vim 也安裝一下 sudo apt-get install vim sudo apt-get install git gnupg flex bison build-essential zip curl zlib1g-dev libc6-dev-i386 x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip font…

防止勒索病毒的兜底方案——備份

勒索病毒入侵會對您的業務數據進行加密勒索,導致業務中斷、數據泄露、數據丟失等,從而帶來嚴重的業務風險。 防止勒索病毒有三個方向: 1)實時防御已知勒索病毒 各個云廠商的云安全中心實現了對大量已知勒索病毒的實時防御。在服務…

es在已有歷史數據的文檔新增加字段操作

新增字段設置默認值 場景 在已經有大量數據的索引文檔上,增加新字段 技術實現 一.更新索引映射 通過PUT請求顯式定義新字段類型,確保后續寫入的文檔能被正確解析 PUT /文檔名/_mapping {"properties": {"字段名1": {"type…

留給王小川的時間不多了

王小川,這位頭頂“天才少年”光環的清華學霸、搜狗輸入法創始人、中國互聯網初代技術偶像,正迎來人生中最難啃的硬骨頭。 他在2023年創立的百川智能,被稱為“大模型六小虎”之一。今年4月,王小川在全員信中罕見地反思過去兩年工作…

深入掌握MyBatis:連接池、動態SQL、多表查詢與緩存

文章目錄 一、MyBatis連接池1.1 連接池的作用1.2 MyBatis連接池分類 二、動態SQL2.1 if標簽2.2 where標簽2.3 foreach標簽2.4 SQL片段復用 三、多表查詢3.1 多對一查詢(一對一)3.2 一對多查詢 四、延遲加載4.1 立即加載 vs 延遲加載4.2 配置延遲加載 五、…

TDesign AI Chat - Vue3.x 可用!騰訊出品的 AIGC 交互對話組件,免費開源、包含設計資源

各位前端開發者有遇到做 AI Chat 項目的聊天交互界面需求了嗎?TDesign 出品的這個組件很不錯,推薦給大家。 TDesign AI Chat 是 TDesign 為 AIGC 場景開發的 UI 系列組件中的一部分,主要用于開發目前非常流行的 ChatBot 對話交互場景。最近 …

spring -MVC-02

SpringMVC-11 - 響應 在 SpringMVC 中,響應是服務器對客戶端請求的反饋,它可以以多種形式呈現,包括視圖名稱、ModelAndView 對象、JSON 數據以及重定向等。以下是對 SpringMVC 中不同響應類型的詳細介紹: 1. 視圖名稱 通過返回…

老舊設備升級利器:Modbus TCP轉 Profinet讓能效監控更智能

在工業自動化領域,ModbusTCP和Profinet是兩種常見的通訊協議。Profinet是西門子公司推出的基于以太網的實時工業以太網標準,而Modbus則是由施耐德電氣提出的全球首個真正開放的、應用于電子控制器上的現場總線協議。這兩種協議各有各的優點,但…

ubuntu下docker安裝mongodb-支持單副本集

1.mogodb支持事務的前提 1) MongoDB 版本:確保 MongoDB 版本大于或等于 4.0,因為事務支持是在 4.0 版本中引入的。 2) 副本集配置:MongoDB 必須以副本集(Replica Set)模式運行,即使是單節點副本集&#x…

【前端開發】Uniapp日期時間選擇器:實現分鐘動態步長設置

技術棧 Uniapp + Vue3 + uView年份顯示前后一年,分鐘動態設置間隔效果圖 主體顯示<view class="uni-row-between selector"><view class="uni-flex-1 left" @click="!props.disabled && openPicker()"><uni-iconscolor=…

iOS 藍牙開發中的 BT 與 BLE

在 iOS 開發者的語境里&#xff0c;大家把 BT 和 BLE 當成兩種不同的藍牙技術在談——它們來自同一個 Bluetooth 規范&#xff0c;但面向的場景、協議棧乃至 Apple 提供的 API 都截然不同。 縮寫全稱 / 技術名稱規范層叫法iOS 支持現狀典型用途BTBluetooth Classic&#xff08…

Flink CEP是什么?

Apache Flink 的 CEP&#xff08;Complex Event Processing&#xff0c;復雜事件處理&#xff09; 是 Flink 提供的一個庫&#xff0c;用于在無界數據流中檢測符合特定模式的事件組合。 &#x1f3af; 一、什么是 CEP&#xff1f; ? 定義&#xff1a; CEP 是一種從連續的數據…

ARM (Attention Refinement Module)

ARM模塊【來源于BiSeNet】&#xff1a;細化特征圖的注意力&#xff0c;增強重要特征并抑制不重要的特征。 Attention Refinement Module (ARM) 詳解 ARM (Attention Refinement Module) 是 BiSeNet 中用于增強特征表示的關鍵模塊&#xff0c;它通過注意力機制來細化特征圖&…

AR0144CSSC20SUKA0-CRBR——1/4英寸 1.0 MP 高性能CMOS圖像傳感器解析

產品概述&#xff1a; AR0144CSSC20SUKA0-CRBR 是一款1/4 英寸&#xff0c;1.0 Mp CMOS 數字圖像傳感器&#xff0c;帶有 1280H x 800V 有效像素陣列 全局快門CMOS數字圖像傳感器&#xff0c;它結合了新型的創新全局快門像素設計&#xff0c;適用于準確快速的移動場景捕捉。該…

深入理解遞歸算法:Go語言實現指南

深入理解遞歸算法&#xff1a;Go語言實現指南 引言 遞歸是編程中一種優雅而強大的算法思想&#xff0c;通過函數自我調用的方式解決復雜問題。本文將使用Go語言演示遞歸的核心原理&#xff0c;并通過典型示例幫助開發者掌握這一重要技術。 一、遞歸基礎概念 1.1 遞歸定義 遞歸…