首先我们利用NodeJs先构建一个基本的服务器。
index.js
var requestHandler = require("./requestHandler");
var server = require("./server");
var route = {
"/hello": requestHandler.hello,
"/upload": requestHandler.upload
};
server.start(route);
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);
}
return false;
}
return true;
};
this.writeHeaders(req.headers);
var self = this;
req
.on('error', function(err) {
self._error(err);
})
.on('aborted', function() {
self.emit('aborted');
})
.on('data', function(buffer) {
self.write(buffer);
})
.on('end', function() {
if (self.error) {
return;
}
var err = self._parser.end();
if (err) {
self._error(err);
}
});
if (cb) {
var fields = {}, files = {};
this
.on('field', function(name, value) {
fields[name] = value;
})
.on('file', function(name, file) {
files[name] = file;
})
.on('error', function(err) {
cb(err, fields, files);
})
.on('end', function() {
cb(null, fields, files);
});
}
return this;
};
在parse中,将head信息解析出来这段是阻塞的。但是真正上传文件却是在req.on(data)中,是利用了事件驱动,是非阻塞的。也就是说,他的非阻塞模型依赖整个nodeJS事件分派架构。
那么像sleep那样消耗大量计算,但是又不能依赖nodeJS分派架构的时候怎么办?
现在介绍一种,类似于html5 WebWorker的方法。
将requestHandler.js改造如下:
var childProcess = require("child_process");
exports.hello = function(res) {
var n = childProcess.fork(__dirname + "/subProcess.js");
n.on('message', function() {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("say hello.");
res.end();
});
n.send({});
};
exports.upload = function(res) {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("upload");
res.end();
};
并加入subProcess.js
function sleep(milliSecond) {
var startTime = new Date().getTime();
console.log(startTime);
while(new Date().getTime() <= milliSecond + startTime) {
}
console.log(new Date().getTime());
}
process.on('message', function() {
sleep(20000);
process.send({});
});
测试,当hello还在等待时,upload已经返回。
分享到:
相关推荐
NodeJs中的非阻塞方法介绍,需要的朋友可以参考下
Node.js体系结构环回域使用环回和域层的NodeJS 9非阻塞I / O架构要求NodeJS 9以上堆JavaScript的6 回送3.x 回送启动2.x 回送资源管理器5.x 回送限制最大值1.x 回送MySQL 5.x环回企业架构在实际应用中,我们需要具有...
通过异步处理大并发例子
Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型。Node 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。发布于2009年5月,由Ryan...
在这个例子中主要讲解 nodejs的回调函数,阻塞代码实例和非阻塞代码实例
更进一步,nodejs引入了非阻塞的 I/O ,从而将异步的概念扩展到了文件访问、网络调用等。 今天,我们将会深入的探讨一下各种异步编程的优缺点和发展趋势。 在讨论nodejs的异步编程之前,让我们来讨论一个比较...
NodeJS被打上了单线程、非阻塞、事件驱动…..等标签。 在单线程的情况下,是无法开启子线程的。经过了很久的研究,发现并没有thread函数!!!但是有时候,我们确实需要“多线程”处理事务。nodeJS有两个很基础的api...
这节我们来了解一下nodejs实现非阻塞操作的方法。 我们先来修改一下 start的处理程序: 代码如下: var exec = require(“child_process”).exec; function start() { console.log(“Request handler ‘start’ ...
Node.js 是一个开源与跨平台的 ... Node.js 在其标准库中提供了一组异步的 I/O 原生功能(用以防止 JavaScript 代码被阻塞),并且 Node.js 中的库通常是使用非阻塞的范式编写的(从而使阻塞行为成为例外而不是规范)。
Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型。 [1] Node 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。 [2] 发布于2009...
灵活且超轻量级的库,用于使用 Future 模式、回调(NodeJS 风格)和异步非阻塞编程。 动机 该库的第一个目标是为 Java 8 提供模式的轻量级实现。此外,该库还提供对 Java 流水线的支持。 第二个目的是演示 Java 8 ...
Node.js使用了一个事件驱动、非阻塞式I/O的模型( Node.js的特性),使其轻量级又高效 npm,Node Package Manager,nodejs 包管理工具。在安装的 nodejs 的时候,npm 也会跟着一起安装,它是包管理工具。npm 管理 ...
Node.js是一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络...Node.js 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行的数据密集型的实时应用。
众所周知,nodejs是用非阻塞异步io机制,也就是说函数执行完成的先后顺序和代码的编写的先后顺序可能不同,实际的顺序取决于一个函数自身执行的快慢。这就出现一个在nodejs中怎么编写串行执行也就是顺序执行代码的...
Node.js是一个Javascript运行环境(runtime)。实际上它是对Google V8引擎进行了封装。...Node.js 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行数据密集型的实时应用。
Node.js 使用高效、轻量级的事件驱动、非阻塞 I/O 模型。Node.js 的生态系统是目前最大的开源包管理系统。 Node.js 是一套用来编写高性能网络服务器的 JavaScript 工具包,一系列的变化由此开始。比较独特的是,...
Node.js是一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络...Node.js 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行的数据密集型的实时应用。
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。