深入淺出Node.js(七):Connect模塊解析(之一)作者 田永強(qiáng) 發(fā)布于 2012年6月5日
Connect模塊背景Node.js的愿望是成為一個(gè)能構(gòu)建高速,可伸縮的網(wǎng)絡(luò)應(yīng)用的平臺,它本身具有基于事件,異步,非阻塞,回調(diào)等特性,這在前幾篇專欄中有過描述。
正是基于這樣的一些特性,Node.js平臺上的Web框架也具有不同于其他平臺的一些特性,其中Connect是眾多Web框架中的佼佼者。
Connect自身十分簡單,其作用是基于Web服務(wù)器做中間件管理。至于如何如何處理網(wǎng)絡(luò)請求,這些任務(wù)通過路由分派給管理的中間件們進(jìn)行處理。
它的處理模型僅僅只是一個(gè)中間隊(duì)列,進(jìn)行流式處理而已,流式處理可能性能不是最優(yōu),但是卻是最易于被理解和接受?;谥虚g件可以自由組合和插拔的情況,優(yōu)
化它十分容易。 中間件讓我們回顧一下Node.js最簡單的Web服務(wù)器是如何編寫的: var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
我們從最樸素的Web服務(wù)器處理流程開始,可以看到HTTP模塊基于事件處理網(wǎng)絡(luò)訪問無外乎兩個(gè)主要的因素,請求和響應(yīng)。同理的是Connect的中間件也是扮演這樣一個(gè)角色,處理請求,然后響應(yīng)客戶端或是讓下一個(gè)中間件繼續(xù)處理。如下是一個(gè)中間件最樸素的原型: function (req, res, next) {
// 中間件
}
在中間件的上下文中,有著三個(gè)變量。分別代表請求對象、響應(yīng)對象、下一個(gè)中間件。如果當(dāng)前中間件調(diào)用了res.end()結(jié)束了響應(yīng),執(zhí)行下一個(gè)中間件就顯得沒有必要。 流式處理為了演示中間件的流式處理,我們可以看看中間件的使用形式: var app = connect();
// Middleware
app.use(connect.staticCache());
app.use(connect.static(__dirname + '/public'));
app.use(connect.cookieParser());
app.use(connect.session());
app.use(connect.query());
app.use(connect.bodyParser());
app.use(connect.csrf());
app.use(function (req, res, next) {
// 中間件
});
app.listen(3001);
Conncet提供use方法用于注冊中間件到一個(gè)Connect對象的隊(duì)列中,我們稱該隊(duì)列叫做中間件隊(duì)列。
Conncet的部分核心代碼如下,它通過use方法來維護(hù)一個(gè)中間件隊(duì)列。然后在請求來臨的時(shí)候,依次調(diào)用隊(duì)列中的中間件,直到某個(gè)中間件不再調(diào)用下一個(gè)中間件為止。 app.stack = [];
app.use = function(route, fn){
// …
// add the middleware
debug('use %s %s', route || '/', fn.name || 'anonymous');
this.stack.push({ route: route, handle: fn });
return this;
};
值得注意的是,必須要有一個(gè)中間件調(diào)用res.end()方法來告知客戶端請求已被處理完成,否則客戶端將一直處于等待狀態(tài)。 路由從前文可以看到其實(shí)app.use()方法接受兩個(gè)參數(shù),route和fn,既路由信息和中間件函數(shù),一個(gè)完整的中間件,其實(shí)包含路由信息和中間件函數(shù)。路由信息的作用是過濾不匹配的URL。請求在遇見路由信息不匹配時(shí),直接傳遞給下一個(gè)中間件處理。 app.use("/upload", connect.multipart({ uploadDir: path }));
加上精確的路由信息后,可以將問題減小。 MVC目錄借助Connect可以自由定制中間件的優(yōu)勢,可以自行提升性能或是設(shè)計(jì)出適合自己需要的項(xiàng)目。Connect自身提供了路由功能,在此基礎(chǔ)上,可 以輕松搭建MVC模式的框架,以達(dá)到開發(fā)效率和執(zhí)行效率的平衡。以下是筆者項(xiàng)目中采用的目錄結(jié)構(gòu),清晰地劃分目錄結(jié)構(gòu)可以幫助劃分代碼的職責(zé),此處僅供參 考。 ├── Makefile // 構(gòu)建文件,通常用于啟動單元測試運(yùn)行等操作 ├── app.js // 應(yīng)用文件 ├── automation // 自動化測試目錄 ├── bin // 存放啟動應(yīng)用相關(guān)腳本的目錄 ├── conf // 配置文件目錄 ├── controllers // 控制層目錄 ├── helpers // 幫助類庫 ├── middlewares // 自定義中間件目錄 ├── models // 數(shù)據(jù)層目錄 ├── node_modules // 第三方模塊目錄 ├── package.json // 項(xiàng)目包描述文件 ├── public // 靜態(tài)文件目錄 │ ├── images // 圖片目錄 │ ├── libs // 第三方前端JavaScript庫目錄 │ ├── scripts // 前端JavaScript腳本目錄 │ └── styles // 樣式表目錄 ├── test // 單元測試目錄 └── views // 視圖層目錄 參考:
關(guān)于作者田永強(qiáng),新浪微博@樸靈,前端工程師,曾就職于SAP,現(xiàn)就職于淘寶,花名樸靈,致力于NodeJS和Mobile Web App方面的研發(fā)工作。雙修前后端JavaScript,寄望將NodeJS引薦給更多的工程師。興趣:讀萬卷書,行萬里路。個(gè)人Github地址:http://github.com/JacksonTian。 |
|
|