node.js最大的卖点在于完全异步的I/O模型。
比于阻塞I/O,异步I/O模型极大提高web服务的并发性(可以参见我在另外一个问题的回答http://www.zhihu.com/question/20122137,node.js在各个平台上使用epoll,kqueue和IOCP等I/O事件框架)。对于I/O密集型应用来说,会有明显的性能提升。例如

  • 对于大量采用Ajax long-polling的网站(典型的如聊天室,知乎的通知推送)能带来很大的提升;因为每一个的long-polling请求都会占用服务器的连接数,虽然大部分连接处在空闲状态,但并发性不强的web框架最终会被大量的连接耗死。而node.js的异步I/O模型最适合于处理这样的情形。
  • 单线程不仅没有降低吞吐率(因为异步),也远离了死锁等同步不当导致的问题。有人会说node.js只有一个线程,不能很好的利用CPU;但实际上这不是问题:node.js可以通过多进程来提高并发能力;其次单进程多线程的程序往往在内存中共享数据,而内存不能跨机器访问,因此限制了扩展到集群的能力。

同时,在非技术层面上:

  • node.js基于js语言,相比于Go, Erlang,Scala等,目前大部分js程序员主要做的都是前端工作,对于HTTP协议等都具备相当的了解,熟练的js攻城狮只要稍加学习就能转到node.js平台上。因此很更容易招到程序员。
  • 良好的社区支持,github上星标最多的那些项目,很大部分都是node.js。至少目前,node.js社区基本具备了搭建一个复杂web应用可能用到的库。我甚至认为node.js的社区现状要好于Python的twisted和ternado。
  • 前后端语言统一,相当一部分的node.js库还能同时应用于网页前端(如http://socket.io库),技术成本进一步下降。尤其在小公司,一个程序猿往往兼顾前后端。

当然node.js也不是没有缺点的,
先说非技术的:

  • node.js诞生于2009年,十分年轻,必然有诸多不成熟的地方,更别说广大社区维护的组件。这一点只能靠时间来检验。

其次是是异步带来的一些问题,:

  • 层层嵌套的回调,异常难以处理。由于程序的模型变成了异步,node.js的代码风格亦偏函数式,没有太多js开发经验的程序员需要一定的时间来适应。
  • 调试工具和手段尚匮乏;

提问者提到的层层嵌套等便是第一个问题,就是如何组织异步控制流的问题。目前在node.js社区中,有async、step、和我编写的xchain等库解决了这个问题。都将嵌套的异步回调平铺开来。
此外express框架的基础connect框架,也通过中间件的思想,也避免了异步回调的嵌套。既然提问者有express的经验,就拿它举个例子:

用express框架新手容易写出这样的代码:
app.get(‘/’, function(req, res) {
db.query(…, function(err, val1) {
if (err) {
// Handle error
} else {
db.query(…, function(err, val2) {
if (err) {
// Handle error
} else {
res.render(‘template’, {val1 : val1, val2 : val2};
}
}
}
});
});
可以看到,首先嵌套随着流程的复杂而变深,其次异常处理十分繁琐。
但是如果了解过connect框架的程序员则不然,在connect框架中,把传给get的回调函数(包括传给app.configure()的那些函数)称作中间件,中间件可以传入很多个,并且依次调用。
app.get(‘/’, function(req, res, next) {
db.query(…, function(err, val1) {
if (err) next(err);
else {
req.val1 = val1;
next();
}
});
}, function(req, res, next) {
db.query(…, function(err, val2) {
if (err) next(err);
else {
req.val2 = val2;
res.render(‘template’, {val1 : req.va1, val2 : req.val2});
}
});
});
这个多出来的next参数便是connect框架解决用于嵌套过深的引入的函数。如果调用next时传以参数,则该参数会当作错误,跳过剩下所有中间件,调用错误处理;否则调用下一个中间件。如此吧缩进控制在可接受的范围内,并且中间件保持独立性有利于复用。

— 完 —

本文作者:蓝形参

【知乎日报】
你都看到这啦,快来点我嘛 Σ(▼□▼メ)

此问题还有 13 个回答,查看全部。
延伸阅读:
有 JavaScript 基础,怎么学习 Node.js?
大家都在用 Node.js 干什么呢?

分享到