NodeJs中的非阻塞方法介紹
2024-05-06 14:21:45
供稿:網友
首先我們利用NodeJs先構建一個基本的服務器。
index.js
代碼如下:
var requestHandler = require("./requestHandler");
var server = require("./server");
var route = {
"/hello": requestHandler.hello,
"/upload": requestHandler.upload
};
server.start(route);
server.js
代碼如下:
server.js
代碼如下:
var http = require("http");
var url = require("url");
exports.start = function(route) {
var server = http.createServer(function(req, res) {
var pathName = url.parse(req.url).pathname;
var handler = route[pathName];
if (handler) {
console.log("Through path:" + pathName + ":" + new Date().getTime());
handler(res);
} else {
res.writeHead(404, {"Content-Type": "text/plain"});
res.end();
}
});
server.listen(8088);
};
requestHandler.js
代碼如下:
exports.hello = function(res) {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("say hello.");
res.end();
};
exports.upload = function(res) {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("upload");
res.end();
};
在cmd中,鍵入node index.js即可啟動。
但是,上面的代碼是阻塞的。如果在createServer的回調函數中,有花費長時間的計算。那么會阻塞node.js的事件輪詢。
NodeJS中,他的高效,關鍵在于快速的返回事件循環。
我們將requestHandler.js改造如下,在這個例子中,由于事件循環一直被sleep函數阻塞著,導致createServer的callback無法及時返回。
代碼如下:
function sleep(milliSecond) {
var startTime = new Date().getTime();
console.log(startTime);
while(new Date().getTime() <= milliSecond + startTime) {
}
console.log(new Date().getTime());
}
exports.hello = function(res) {
sleep(20000);
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("say hello.");
res.end();
};
exports.upload = function(res) {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("upload");
res.end();
};
那么先鍵入http://localhost:8088/hello,后鍵入http://localhost:8088/upload。你會發現,upload雖然不需要花費太多時間,但是卻要等到hello完成。
我們試圖找尋異步調用的方法。比如formidable中的上傳,經測試是非阻塞的。查看formidable的源碼,發現最關鍵的是下面的代碼:
代碼如下:
IncomingForm.prototype.parse = function(req, cb) {
this.pause = function() {
try {
req.pause();
} catch (err) {
// the stream was destroyed
if (!this.ended) {
// before it was completed, crash & burn
this._error(err);
}
return false;
}
return true;
};
this.resume = function() {
try {
req.resume();
} catch (err) {
// the stream was destroyed
if (!this.ended) {
// before it was completed, crash & burn
this._error(err);
}