script:
$ cat server.js
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200);
res.write('hello world!');
res.end();
var OutgoingMessage = require('_http_outgoing').OutgoingMessage; | |
var automaticHeaders = { | |
connection: true, | |
'content-length': true, | |
'transfer-encoding': true, | |
date: true | |
}; | |
OutgoingMessage.prototype.setHeader1 = function(name, value) { |
script:
$ cat server.js
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200);
res.write('hello world!');
res.end();
var http = require('http');
http.createServer(function (req, res) {
if (req.url === '/1') {
res.writeHead(200);
res.end('hello world!');
} else {
res.writeHead(200);
res.write('hello world!');
server.js
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200);
res.end('hello world!');
}).listen(1334);
$ node test_args.js
[ 'unknown', undefined ]
[ 'unknown', undefined ]
[ 'unknown', undefined ]
[ 'message', undefined ]
[ 'message', undefined ]
[ 'message', undefined ]
[ 'unknown', {} ]
[ 'unknown', {} ]
Node.js擅长数据密集型实时(data-intensive real-time)交互的应用场景。然而数据密集型实时应用程序并不是只有I/O密集型任务,当碰到CPU密集型任务时,比如要对数据加解密(node.bcrypt.js),数据压缩和解压(node-tar),或者要根据用户的身份对图片做些个性化处理,在这些场景下,主线程致力于做复杂的CPU计算,I/O请求队列中的任务就被阻塞。
Node.js主线程的event loop在处理所有的任务/事件时,都是沿着事件队列顺序执行的,所以在其中任何一个任务/事件本身没有完成之前,其它的回调、监听器、超时、nextTick()的函数都得不到运行的机会,因为被阻塞的event loop根本没机会处理它们,此时程序最好的情况是变慢,最糟的情况是停滞不动,像死掉一样。
一个可行的解决方案是新开进程,通过IPC通信,将CPU密集型任务交给子进程,子进程计算完毕后,再通过ipc消息通知主进程,并将结果返回给主进程。
和创建线程相比,开辟新进程的系统资源占用率大,进程间通信效率也不高。如果能不开新进程而是新开线程,将CPU耗时任务交给一个工作线程去做,然后主线程立即返回,处理其他的I/O请求,等到工作线程计算完毕后,通知主线程并将结果返回给主线程。那么在同时面对I/O密集型和CPU密集型服务的场景下,Node的主线程也会变得轻松,并能时刻保持高响应度。
在《深入浅出Node.js》的第4章里,笔者深度地介绍了当前盛行在Node和前端JavaScript中的几种异步编程的解决方案,唯独对Generator的解决方案没有介绍。但随着Node版本的升级和ECMAScript harmony的特性不断得到支持,0.11中,通过启用--harmory
参数,可以让V8支持Generator。最近Connect/Express背后的开发团队也将精力转移到新的库和框架上,这个核心库和框架就是co
和koa
,它们最主要的特点就是主要基于ECMAScript harmony中的Generator特性,这使得它在异步编程方面有较优雅的实现。
本文将深度介绍下Generator是如何实现将异步编程从原始的嵌套式代码转换成扁平的顺序式代码。
简单地回顾下,异步编程的问题主要有必须通过回调函数进行返回值的处理,以及复杂情况下会造成嵌套过深的问题。这里简单地给出两种典型的异步场景。
异步串行读取文件:
var argv = process.argv.slice(2); | |
if (argv.length !== 3) { | |
console.log('enter 3 number, please.'); | |
return; | |
} | |
if (argv[0] === argv[1] && argv[1] === argv[2]) { | |
console.log("equal"); | |
} else { | |
console.log("not equal"); |
app.get('/index.html', function (req, res) { | |
var data = []; | |
var count = 0; | |
// 渲染到客户端 | |
var render = function () { | |
if (count === 2) { | |
res.end(_.template('tpl', { | |
data: data; | |
})) | |
} |