版權聲明:此文首發於個人我的站Keyon Y,轉載請註明出處。前端
項目地址:github.com/KeyonY/Node…node
express的邏輯處理分爲兩部分:轉發後端接口和中間件webpack
後端提供的接口分爲兩類:ios
就是url的連接所能訪問的頁面。git
先使用router.get()註冊路由,路由內先經過axios訪問後端獲取頁面數據response,經過 res.render()返回一個自定義的對象,將response做爲對象的屬性傳遞到pug模板頁面中,在pug頁面中即可以隨意使用response。github
參考github項目中 config/routes/default.js文件:web
// 首頁
router.get('/', addUser, (req, res, next) => {
axios.all([
axios.get('/Api/Carous'),
axios.get('/Api/Cars/Top10', {params: {page: req.query.page || 1}}),
])
.then(axios.spread(function (res1, res2){
config.throwError(next, res1, res2);
var page = req.query.page || 1;
res.render('Default/index', {
title: config.title('首頁'),
keywords: config.keywords,
description: config.description,
menuNav: 0,
carList: res1.data.Data,
top10: res2.data.Data.slice((page-1)*3,page*3)
});
})).catch(e => {
config.renderError(req, res, e);
})
});
複製代碼
是前端發送ajax請求的接口。ajax
與數據接口的區別就是,中間層只作兩件事:express
// get請求
router.get('/User/Role', (req, res, next) => {
axios.get(config.origin + '/Api/User/Role', config.axiosHeaders(req, {
params: {role: req.query.role}
}))
.then(res1 => {
res.send(res1.data);
}).catch(e => {
config.sendError(res, e);
})
})
// post請求
router.post('/User/SendRequest', (req, res, next) => {
axios.post(config.origin + '/Api/User/SendRequest', {
userID: req.body.userID || null,
requestID: JSON.parse(req.body.requestID) || null
}, config.axiosHeaders(req))
.then((res2) => {
res.send(res2.data);
}).catch((e) => {
config.sendError(res, e);
})
});
複製代碼
post請求沒法直接讀取請求體,須要安裝body-parser依賴npm
npm i –save body-parser
並在app.js掛載這個依賴
app.use(bodyParser.urlencoded({extended: false}));
複製代碼
分爲三種狀況:
router.get('/Cars/:id', (req, res, next) => {
axios.get(config.origin + '/Api/Cars', {
params: {role: req.params.id} // req.params.id獲取url中的參數
}))
...
})
複製代碼
// 例如這樣的請求 /Cars/Search?q=tobi
router.get('/Cars/Search', (req, res, next) => {
axios.get(config.origin + '/Api/Cars/Search', {
params: {car: req.query.q} // req.query.q獲取參數
}))
...
})
複製代碼
router.post('/Cars/Search', (req, res, next) => {
axios.post(config.origin + '/Api/Cars/Search', {
car: req.body.name // req.body.name獲取請求體中的參數
}))
...
})
複製代碼
express post請求,獲取客戶端請求中的數組時,如果直接post一個數組,則express沒法獲取數組,須要在客戶端對數組進行序列化,在中間層反序列化:
// 客戶端
$.ajax({
url: '/Api/Mas/SendInfo',
type: 'POST',
data: {userID: userId, requestID: JSON.stringify(selected)}, // 序列化
success: function (res) {
log(res);
if(res.Status == 0){
$thisModal.hide();
$('#modal_cds').show();
}
}
})
// 中間層
axios.post(config.origin + '/Api/Mas/SendInfo', {
userID: req.body.userID || null,
requestID: JSON.parse(req.body.requestID) || null // 反序列化
}, config.axiosHeaders(req))
複製代碼
千萬不要在中間層傳遞有可能不存在的property!
千萬不要在中間層傳遞有可能不存在的property!
千萬不要在中間層傳遞有可能不存在的property!
重要的事情說三遍,否則出現下面的bug 都不知道在哪裏找。
(node:20352) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot read property ‘data’ of undefined
Express 是一個自身功能極簡,徹底是由路由和中間件構成一個的 web 開發框架:從本質上來講,一個 Express 應用就是在調用各類中間件。
中間件(Middleware) 是一個函數,它能夠訪問請求對象(request object (req)
), 響應對象(response object (res)
), 和 web 應用中處於請求-響應循環流程中的中間件,通常被命名爲 next 的變量。
中間件的功能包括:
若是當前中間件沒有終結請求-響應循環,則必須調用 next() 方法將控制權交給下一個中間件,不然請求就會掛起。
Express 應用可以使用以下幾種中間件:
使用可選擇掛載路徑,可在應用級別或路由級別裝載中間件。另外,你還能夠同時裝載一系列中間件函數,從而在一個掛載點上建立一個子中間件棧。
var addUser = require('../../middleware/addUser');
...
router.get('/Car/List', addUser, (req, res, next) => {
...
})
複製代碼
addUser即中間件,是一個方法,接受路由中的req,res,next三個參數,必須以**next();**結束代碼,這樣將函數指針從addUser,交給(req, res, next) => { …}。
使用中間件,能夠獲取請求頭中的cookies,以驗證用戶登陸信息
獲取cookie的內容,須要安裝cookie-parser依賴
npm i –save cookie-parser
在app.js中,掛載這個依賴就可使用了。
app.use(cookieParser());
複製代碼
注意Error Handle的掛載的順序,通常掛載到app.use()下,且放在最後。 請參考本系列博文的第二篇Node中間層實踐(二)——搭建項目框架中app.js的介紹,或查看github項目代碼的app.js。
歡迎繼續關注系列的其餘文章
Node中間層實踐(一)——基於NodeJS的全棧式開發
Node中間層實踐(二)——搭建項目框架
Node中間層實踐(三)——webpack配置
Node中間層實踐(四)——模板引擎pug
Node中間層實踐(五)——express-中間層的邏輯處理