Node.js:顛覆傳統(tǒng)的服務(wù)器端開發(fā)
Node.js是基于Chrome V8引擎構(gòu)建的JavaScript運行時,它采用了完全不同的開發(fā)模型。Node.js使用事件驅(qū)動和非阻塞I/O的方式處理請求,通過單線程和異步機制,實現(xiàn)高效的并發(fā)處理。這意味著在Node.js中,一個線程可以處理數(shù)千個并發(fā)連接,大大提高了服務(wù)器的性能和可伸縮性。
一、認識Web框架
二、Express安裝
三、Express的基本使用
const express = require('express')
// 1.創(chuàng)建express的服務(wù)器
const app = express()
// 客戶端訪問URL: /login和/home
app.post('/login', (req, res) => {
// 處理login請求
res.end('登錄成功, 歡迎回來~')
})
app.get('/home', (req, res) => {
res.end('首頁的輪播圖/推薦數(shù)據(jù)列表~')
})
// 2.啟動服務(wù)器, 并且監(jiān)聽端口
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
四、認識中間件
4.1、注冊普通中間件
const express = require('express')
const app = express()
// 總結(jié): 當express接收到客戶端發(fā)送的網(wǎng)絡(luò)請求時, 在所有中間中開始進行匹配
// 當匹配到第一個符合要求的中間件時, 那么就會執(zhí)行這個中間件
// 后續(xù)的中間件是否會執(zhí)行呢? 取決于上一個中間件有沒有執(zhí)行next
// 通過use方法注冊的中間件是最普通的/簡單的中間件
// 通過use注冊的中間件, 無論是什么請求方式都可以匹配上
// login/get
// login/post
// abc/patch
app.use((req, res, next) => {
console.log('normal middleware 01')
// res.end('返回結(jié)果了, 不要等了')
next()
})
app.use((req, res, next) => {
console.log('normal middleware 02')
})
// 開啟服務(wù)器
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
4.2、注冊路徑匹配的中間件
const express = require('express')
const app = express()
// 注冊普通的中間件
// app.use((req, res, next) => {
// console.log('match normal middleware')
// res.end('--------')
// })
// 注冊路徑匹配的中間件
// 路徑匹配的中間件是不會對請求方式(method)進行限制
app.use('/home', (req, res, next) => {
console.log('match /home middleware')
res.end('home data')
})
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
4.3、方法、路徑匹配的中間件
const express = require('express')
const app = express()
// 注冊中間件: 對path/method都有限制
// app.method(path, middleware)
app.get('/home', (req, res, next) => {
console.log('match /home get method middleware')
res.end('home data')
})
app.post('/users', (req, res, next) => {
console.log('match /users post method middleware')
res.end('create user success')
})
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
4.4、匹配多個中間件
const express = require('express')
const app = express()
// app.get(路徑, 中間件1, 中間件2, 中間件3)
app.get('/home', (req, res, next) => {
console.log('match /home get middleware01')
next()
}, (req, res, next) => {
console.log('match /home get middleware02')
next()
}, (req, res, next) => {
console.log('match /home get middleware03')
next()
}, (req, res, next) => {
console.log('match /home get middleware04')
})
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
4.5、中間件案例一
先匹配普通中間件,有next()才會繼續(xù)向下匹配
const express = require('express')
const app = express()
// 1.注冊兩個普通的中間件
app.use((req, res, next) => {
console.log('normal middleware01')
next()
})
app.use((req, res, next) => {
console.log('normal middleware02')
next()
})
// 2.注冊路徑path/method的中間件
app.get('/home', (req, res, next) => {
console.log('/home get middleware01')
next()
}, (req, res, next) => {
console.log('/home get middleware02')
next()
})
app.post('/login', (req, res, next) => {
console.log('/login post middleware')
next()
})
// 3.注冊普通的中間件
app.use((req, res, next) => {
console.log('normal middleware03')
next()
})
app.use((req, res, next) => {
console.log('normal middleware04')
})
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
4.6、中間件案例二
const express = require('express')
const app = express()
// 注冊兩個實際請求的中間件
// 案例一: 用戶登錄的請求處理 /login post => username/password
app.post('/login', (req, res, next) => {
// 1.獲取本次請求過程中傳遞過來的json數(shù)據(jù)
let isLogin = false
req.on('data', (data) => {
const dataString = data.toString()
const dataInfo = JSON.parse(dataString)
if (dataInfo.username === 'coderwhy' && dataInfo.password === '123456') {
isLogin = true
}
})
req.on('end', () => {
if (isLogin) {
res.end('登錄成功, 歡迎回來~')
} else {
res.end('登錄失敗, 請檢測賬號和密碼是否正確~')
}
})
})
// 案例二: 注冊用戶的請求處理 /register post => username/password
app.post('/register', (req, res, next) => {
// 1.獲取本次請求過程中傳遞過來的json數(shù)據(jù)
let isRegister = false
req.on('data', (data) => {
const dataString = data.toString()
const dataInfo = JSON.parse(dataString)
// 查詢數(shù)據(jù)庫中該用戶是否已經(jīng)注冊過
isRegister = false
})
req.on('end', () => {
if (isRegister) {
res.end('注冊成功, 開始你的旅程~')
} else {
res.end('注冊失敗, 您輸入的用戶名被注冊~')
}
})
})
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
4.7、中間件案例二(重構(gòu))
//下面這個代碼就相當于app.use(express.json())的原理,以后開發(fā)直接用app.use(express.json())
app.use((req, res, next) => {
if (req.headers['content-type'] === 'application/json') {
req.on('data', (data) => {
const jsonInfo = JSON.parse(data.toString())
req.body = jsonInfo
})
req.on('end', () => {
next()
})
} else {
next()
}
})
const express = require('express')
const app = express()
// app.use((req, res, next) => {
// if (req.headers['content-type'] === 'application/json') {
// req.on('data', (data) => {
// const jsonInfo = JSON.parse(data.toString())
// req.body = jsonInfo
// })
// req.on('end', () => {
// next()
// })
// } else {
// next()
// }
// })
// 直接使用express提供給我們的中間件
app.use(express.json())
// 注冊兩個實際請求的中間件
// 案例一: 用戶登錄的請求處理 /login post => username/password
app.post('/login', (req, res, next) => {
console.log(req.body)
})
// 案例二: 注冊用戶的請求處理 /register post => username/password
app.post('/register', (req, res, next) => {
console.log(req.body)
})
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
4.8、中間件應用-urlencoded解析
const express = require('express')
// 創(chuàng)建app對象
const app = express()
// 應用一些中間件
app.use(express.json()) // 解析客戶端傳遞過來的json
// 解析傳遞過來urlencoded的時候, 默認使用的node內(nèi)置querystring模塊
// { extended: true }: 不再使用內(nèi)置的querystring, 而是使用qs第三方庫
app.use(express.urlencoded({ extended: true })) // 解析客戶端傳遞過來的urlencoded
// 編寫中間件
app.post('/login', (req, res, next) => {
console.log(req.body)
res.end('登錄成功, 歡迎回來~')
})
// 啟動服務(wù)器
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
4.9、應用中間件 – 第三方中間件
//記錄日志
const fs = require('fs')
const express = require('express')
const morgan = require('morgan')
// 創(chuàng)建app對象
const app = express()
// 應用第三方中間件
const writeStream = fs.createWriteStream('./logs/access.log')
app.use(morgan('combined', { stream: writeStream }))
// 編寫中間件
app.post('/login', (req, res, next) => {
res.end('登錄成功, 歡迎回來~')
})
// 啟動服務(wù)器
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
單個文件上傳
const express = require('express')
const multer = require('multer')
// 創(chuàng)建app對象
const app = express()
// 應用一個express編寫第三方的中間件
const upload = multer({
dest: './uploads'
})
// 編寫中間件
// 上傳單文件: singer方法
app.post('/avatar', upload.single('avatar') , (req, res, next) => {
console.log(req.file)
res.end('文件上傳成功~')
})
// 啟動服務(wù)器
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
4.9、中間件應用-多個文件上傳
const express = require('express')
const multer = require('multer')
// 創(chuàng)建app對象
const app = express()
// 應用一個express編寫第三方的中間件
const upload = multer({
// dest: './uploads'
storage: multer.diskStorage({
destination(req, file, callback) {
callback(null, './uploads')
},
// 自定義文件名
filename(req, file, callback) {
callback(null, Date.now() + '_' + file.originalname)
}
})
})
// 編寫中間件
// 上傳單文件: single方法
app.post('/avatar', upload.single('avatar') , (req, res, next) => {
console.log(req.file)
res.end('文件上傳成功~')
})
// 上傳多文件:
app.post('/photos', upload.array('photos'), (req, res, next) => {
console.log(req.files)
res.end('上傳多張照片成功~')
})
// 啟動服務(wù)器
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
5.0、中間件應用-formdata解析
const express = require('express')
const multer = require('multer')
// 創(chuàng)建app對象
const app = express()
// express內(nèi)置的插件
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
// 編寫中間件
const formdata = multer()
app.post('/login', formdata.any(), (req, res, next) => {
console.log(req.body)
res.end('登錄成功, 歡迎回來~')
})
// 啟動服務(wù)器
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
5.1、客戶端參數(shù)解析
const express = require('express')
// 創(chuàng)建app對象
const app = express()
// 編寫中間件
// 1.解析queryString
app.get('/home/list', (req, res, next) => {
// offset/size
const queryInfo = req.query
console.log(queryInfo)
res.end('data list數(shù)據(jù)')
})
// 2.解析params參數(shù)
app.get('/users/:id', (req, res, next) => {
const id = req.params.id
res.end(`獲取到${id}的數(shù)據(jù)~`)
})
// 啟動服務(wù)器
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
5.2、服務(wù)器響應數(shù)據(jù)類型
const express = require('express')
// 創(chuàng)建app對象
const app = express()
// 編寫中間件
app.post('/login', (req, res, next) => {
// 1.res.end方法(比較少)
// res.end('登錄成功, 歡迎回來~')
// 2.res.json方法(最多)
// res.json({
// code: 200,
// message: '歡迎回來~',
// list: [
// { name: 'iPhone', price: 111 },
// { name: 'iPad', price: 111 },
// { name: 'iMac', price: 111 },
// { name: 'Mac', price: 111 },
// ]
// })
// 3.res.status方法: 設(shè)置http狀態(tài)碼
res.status(201)
res.json('創(chuàng)建用戶成功~')
})
// 啟動服務(wù)器
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
5.3、Express的路由
文章來源:http://www.zghlxwxcb.cn/news/detail-627020.html
router/userRouter.js文章來源地址http://www.zghlxwxcb.cn/news/detail-627020.html
const express = require('express')
// 1.創(chuàng)建路由對象
const userRouter = express.Router()
// 2.定義路由對象中的映射接口
userRouter.get('/', (req, res, next) => {
res.json('用戶列表數(shù)據(jù)')
})
userRouter.get('/:id', (req, res, next) => {
const id = req.params.id
res.json('某一個用戶的數(shù)據(jù):' + id)
})
userRouter.post('/', (req, res, next) => {
res.json('創(chuàng)建用戶成功')
})
userRouter.delete('/:id', (req, res, next) => {
const id = req.params.id
res.json('刪除某一個用戶的數(shù)據(jù):' + id)
})
userRouter.patch('/:id', (req, res, next) => {
const id = req.params.id
res.json('修改某一個用戶的數(shù)據(jù):' + id)
})
// 3.將路由導出
module.exports = userRouter
const express = require('express')
const userRouter = require('./router/userRouter')
// 創(chuàng)建app對象
const app = express()
// 編寫中間件
app.post('/login', (req, res, next) => {
})
app.get('/home', (req, res, next) => {
})
/** 用戶的接口 */
// 1.將用戶的接口直接定義在app中
// app.get('/users', (req, res, next) => {})
// app.get('/users/:id', (req, res, next) => {})
// app.post('/users', (req, res, next) => {})
// app.delete('/users/:id', (req, res, next) => {})
// app.patch('/users/:id', (req, res, next) => {})
// 2.將用戶的接口定義在單獨的路由對象中
// const userRouter = express.Router()
// userRouter.get('/', (req, res, next) => {
// res.json('用戶列表數(shù)據(jù)')
// })
// userRouter.get('/:id', (req, res, next) => {
// const id = req.params.id
// res.json('某一個用戶的數(shù)據(jù):' + id)
// })
// userRouter.post('/', (req, res, next) => {
// res.json('創(chuàng)建用戶成功')
// })
// userRouter.delete('/:id', (req, res, next) => {
// const id = req.params.id
// res.json('刪除某一個用戶的數(shù)據(jù):' + id)
// })
// userRouter.patch('/:id', (req, res, next) => {
// const id = req.params.id
// res.json('修改某一個用戶的數(shù)據(jù):' + id)
// })
// 讓路由生效
app.use('/users', userRouter)
// 啟動服務(wù)器
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
5.4、express的靜態(tài)資源服務(wù)器
const express = require('express')
// 創(chuàng)建app對象
const app = express()
// 內(nèi)置的中間件: 直接將一個文件夾作為靜態(tài)資源
app.use(express.static('./uploads'))
app.use(express.static('./build'))
// 編寫中間件
app.post('/login', (req, res, next) => {
})
// 啟動服務(wù)器
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
5.5、express中錯誤處理的方案
const express = require('express')
// 創(chuàng)建app對象
const app = express()
app.use(express.json())
// 編寫中間件
app.post('/login', (req, res, next) => {
// 1.獲取登錄傳入的用戶名和密碼
const { username, password } = req.body
// 2.對用戶名和密碼進行判斷
if (!username || !password) {
next(-1001)
} else if (username !== 'coderwhy' || password !== '123456') {
next(-1002)
} else {
res.json({
code: 0,
message: '登錄成功, 歡迎回來~',
token: '323dfafadfa3222'
})
}
})
// 錯誤處理的中間件
app.use((errCode, req, res, next) => {
const code = errCode
let message = '未知的錯誤信息'
switch(code) {
case -1001:
message = '沒有輸入用戶名和密碼'
break
case -1002:
message = '輸入用戶名或密碼錯誤'
break
}
res.json({ code, message })
})
// 啟動服務(wù)器
app.listen(9000, () => {
console.log('express服務(wù)器啟動成功~')
})
到了這里,關(guān)于Node.js之express框架學習心得的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!