Express基础
1 簡介
Express是一個基于Node平臺的web應用開發(fā)框架,它提供了一系列的強大特性用來創(chuàng)建各種Web應用。
- 提供了方便簡潔的路由定義方式;
- 對獲取HTTP請求參數(shù)進行了簡化處理;
- 對模板引擎支持程度高,方便渲染動態(tài)HTML頁面;
- 提供了中間件機制有效控制HTTP請求;
- 擁有大量第三方中間件對功能進行擴展。
可以使用 npm install express?命令安裝Express,安裝后包含兩個文件夾:
- node_modules:包含所有依賴包;
- package-lock.json:所有依賴包的清單。
再在根目錄新建文件server.js,具體使用方法見第3節(jié)。
2 原生Node.js與Express框架路由實現(xiàn)對比
2.1 原生Node.js路由
app.on('request', (req, res) => {// 獲取客戶端的請求路徑let {pathname} = url.parse(req.url)// 對請求路徑進行判斷,不同的路徑地址響應不同的內(nèi)容if (pathname == '/' || pathname == 'index') {res.end('歡迎來到首頁!')} else if (pathname == '/other') {res.end('歡迎來到其他頁面!')} else if (pathname == '/about') {res.end('歡迎來到關(guān)于頁面!') } else {res.end('抱歉,沒有找到相關(guān)頁面!')} })2.2 Express路由
// 當客戶端以get方式訪問/時 app.get('/', (req, res) => {// 對客戶端做出響應res.send('使用get方式請求了/路由') })// 當客戶端以post方式訪問/about路由時 app.post('/about', (req, res) => {res.send('使用post方式請求了/about路由') })3 Express框架簡單使用
啟動一個Express網(wǎng)站服務器并開啟一個“/”的路由監(jiān)聽:
// 1.引入Express框架,并創(chuàng)建Express實例 const express = require('express') // 2.創(chuàng)建網(wǎng)站服務器對象 const app = express()// 3.定義路由 // 第一個參數(shù)是請求的路徑,'/'代表根路徑localhost:3000 // 第二個參數(shù)是一個函數(shù),req是request的縮寫,表示客戶端提交過來的數(shù)據(jù) // res是respond的縮寫,表示要響應回的數(shù)據(jù) app.get('/', (req, res) => {// send()方法,響應給客戶端信息// 1. send方法內(nèi)部會檢測響應內(nèi)容的類型// 2. send方法會自動設(shè)置http狀態(tài)碼// 3. send方法會幫我們自動設(shè)置響應的內(nèi)容類型及編碼res.send('Hello Express!') })// 4.監(jiān)聽端口,第二個參數(shù)回調(diào)函數(shù)啟動成功后執(zhí)行的內(nèi)容 app.listen(3000, () => {console.log('網(wǎng)站服務器啟動成功!') })輸入node server.js啟動服務器,但因node項目在每次編輯后都要重新啟動才會生效,所以使用nodemon工具來自動啟動服務,推薦全局安裝,命令如下:
npm install -g nodemon安裝成功后就可以使用命令nodemon server.js來啟動服務。
4 中間件
中間件就是一系列方法,可以接收客戶端發(fā)來的請求、可以對請求做出響應,也可以將請求繼續(xù)交給下一個中間件繼續(xù)處理。
中間件主要由兩部分構(gòu)成,中間件方法以及請求處理函數(shù)。
中間件方法由Express提供,負責攔截請求,請求處理函數(shù)由開發(fā)人員提供,負責處理請求。
可以針對同一個請求設(shè)置多個中間件,對同一個請求進行多次處理。
默認情況下,請求從上到下依次匹配中間件,一旦匹配成功,終止匹配。可以調(diào)用 next()?方法將請求的控制權(quán)交給下一個中間件,直到遇到結(jié)束請求的中間件。
4.1 萬能中間件 app.use
app.use 匹配所有的請求方式,可以直接傳入請求處理函數(shù),代表接收所有的請求。
app.use((req, res, next) => {console.log(req.url)next() })app.use?第一個參數(shù)也可以傳入請求地址,代表不論什么請求方式,只要是這個請求地址就接收這個請求。
app.use('/about', (req, res, next) => {console.log(req.url)next() })4.2 中間件的應用
4.3 處理錯誤中間件
在程序執(zhí)行的過程中,不可避免的會出現(xiàn)一些無法預料的錯誤,比如文件讀取失敗,數(shù)據(jù)庫連接失敗。錯誤處理中間件是一個集中處理錯誤的地方。
app.get('/index', (req, res) => {// 創(chuàng)建一個錯誤實例并拋出throw new Error('程序發(fā)生了未知錯誤!') })app.use((err, req, res, next) => {// 為客戶端響應500狀態(tài)碼以及提示信息res.status(500).send(err.message) })throw new Error('程序發(fā)生了未知錯誤!')?實際上是一個同步代碼,如果異步代碼在執(zhí)行過程中出現(xiàn)了錯誤,這樣是無法捕捉到的。這個時候需要手動的觸發(fā)錯誤處理中間件,當異步API出錯時,需要調(diào)用 next()?方法,并把錯誤傳入 next()?方法。
app.get('/', (req, res, next) => {fs.readFile('/file-does-not-exist', (err, result) => {if (err != null) {next(err)} else {res.send(result)}}) })4.4 捕獲錯誤
在nodejs中,異步API的錯誤信息都是通過回調(diào)函數(shù)獲取的,支持Promise對象的異步API發(fā)生錯誤可以通過catch方法捕獲。異步函數(shù)執(zhí)行如果發(fā)生錯誤要如何捕獲錯誤呢?
try catch?可以捕獲異步函數(shù)以及其他同步代碼在執(zhí)行過程中發(fā)生的錯誤,但是不能其他類型的API發(fā)生的錯誤。下面代碼中把讀取文件改造成支持異步函數(shù)的形式。
const promisify = require('util').promisify const readFile = promisify(fs.readFile)app.get('/', async (req, res, next) => {try {await readFile('/aaa.js')} catch(err) {next(err)} })4.5 構(gòu)建模塊化路由
// 創(chuàng)建路由對象 const home = express.Router() // 將路由和請求路徑進行匹配 app.use('/home', home) // 在home路由下繼續(xù)創(chuàng)建二級路由 home.get('/index', () => {// 訪問路徑/home/indexres.send('歡迎來到主頁!') })5 GET參數(shù)的獲取
Express框架中使用req.query即可獲取GET參數(shù),框架內(nèi)部會將GET參數(shù)轉(zhuǎn)換為對象并返回。
// 接收地址欄中問號后面的參數(shù) // 例如:http://localhost:3000/?name=zhangsan&age=30 app.get('/', (req, res) => {console.log(req.query) // {"name": "zhangsan", "age": "30"} })6 POST參數(shù)的獲取
Express中接收post請求參數(shù)需要借助第三方包 body-parser。它其實是Express官方提供的,官方為了讓包體積更加小巧,將一些工具剝離出來,供開發(fā)者按需安裝。
安裝命令: npm install body-parser?。
注:可以直接使用app.use(express.json());代替body-parser。
【1】https://stackoverflow.com/questions/61551926/express-json-vs-body-parser
【2】https://cloud.tencent.com/developer/ask/37434
7 Express路由參數(shù)
在定義時,可以顯式定義請求接收的參數(shù),在url后面用冒號加上參數(shù):
// localhost:3000/find/123 app.get('/find/:id', (req, res) => {console.log(req.params) // {id: 123} })如果要傳遞多個參數(shù),可以繼續(xù)添加斜杠和冒號。
8 靜態(tài)資源的處理
通過Express內(nèi)置的express.static可以方便地托管靜態(tài)文件,例如img、CSS、JavaScript 文件等。
const path = require('path') app.use(express.static(path.join(__dirname, 'public')))現(xiàn)在,public目錄下面的文件就可以訪問了。
- http://localhost:3000/images/kitten.jpg
- http://localhost:3000/css/style.css
- http://localhost:3000/js/app.js
- http://localhost:3000/images/bg.png
- http://localhost:3000/hello.html
除此之外,還可以控制路徑,可以在添加一個參數(shù)static,
app.use('static', express.static(path.join(__dirname, 'public')))再訪問靜態(tài)資源的時候就要在url中加入static,如:http://localhost:3000/static/hello.html。
9 跨域處理
跨域:https://juejin.cn/post/6844904126246027278#heading-1
現(xiàn)在如有接口:
該接口的訪問地址是:http://localhost:3000/user。使用靜態(tài)資源處理,在public文件夾中新建index.html。
此時通過http://localhost:3000/index.html可以訪問,在body中添加如下內(nèi)容:
再次訪問http://localhost:3000/index.html,就可以在Console中看到輸出的對象:{name: "syz", age: "18"}。
這是數(shù)據(jù)是可以正常訪問到的,此時右鍵index.html,利用vscode插件Live server打卡,該插件會啟動一個以5500為端口的服務:
訪問地址為:http://127.0.0.1:5500/public/index.html,此時可以發(fā)現(xiàn)Console無法請求到數(shù)據(jù)了,并報了跨域錯誤。
處理跨域問題需要用到第三方庫:npm i cors,在server.js中添加如下代碼:
再訪問http://127.0.0.1:5500/public/index.html即可獲取到數(shù)據(jù)。
總結(jié)
- 上一篇: 01-Vue博客后台管理页面框架搭建
- 下一篇: 解决Cesium无法加载出地球的问题