`

Node.js的一些缺点分析(转)

 
阅读更多
身为重度Node.js用户,我也来说说我的理解吧。

计算机语言和技术平台很多时候不是谁更好谁更差的问题,而是谁更合适的问题,这里我们从语言和生态系统两个维度来坐下简要的对比。

语言的对比
JavaScript和Java从语言的设计上来说,虽然都含有Java但是是完全不同的两种语言,简单的说:

JavaScript
JavaScript是其实没法简单的用一句话来解释其设计,大了说,我们可以称他为一种多范式的语言(通常这个词用在C++身上),小了说我们可以把它当成是一种基于原型链的面向对象动态语言来看待。正是这种“灵活性”给各种奇技淫巧带来了可能性,表面上这减少了代码量,给码农们带来了幸福,而实际上,正是因为这种灵活性导致了程序在运行过程中很容易出现难以调试的Bug,而Bug的日志会让人摸不着头脑。
再者JavaScript设计上对异步没有很好的支持,对于Node这种完全异步的平台而言,编写复杂逻辑的应用程序简直就是灾难,举个例子:
通常,同步的逻辑是这样的:
function getForgeMetadata(cid, itemId) {
var character = getCharacter(cid);
var item = getItem(itemId);
var itemDesc = getItemDesc(item.type);
var forgeLevel = getForgeLevel(item);
return getForgeMetadata(character, itemDesc, forgeLevel);
}
然而,如果我们采用node.js中标准的回调格式来编写代码的话,您的代码会变成这样:
function getForgeMetadata(cid, itemId, cb) {
getCharacter(cid, function(err, character) {
if (err) return cb(err);
getItem(itemId, function(err, item) {
if (err) return cb(err);
getItemDesc(item.type, function(err, itemDesc) {
if (err) return cb(err);
var forgeLevel = getForgeLevel(item);
getForgeMetadata(character, itemDesc, forgeLevel, cb);
});
});
});
}
看到那一长串的if (err) return cb(err);你会不会有种想要自杀的感觉,后来终于社区也看不下去了就弄了个async库出来,但基本上差别也不太大,再后来有了promise(通常使用库q来实现),情况略有好转,代码可以变成这样:
function getForgeMetadata(cid, itemId) {
return getCharacter(cid)
.then(function(character) {
return getItem(itemId)
.then(function(item) {
return {'character': character, 'item': item};
});
};
}).then(function(meta) {
return getItemDesc(meta.item.type)
.then(function(itemDesc) {
meta.itemDesc = itemDesc;
return meta;
});
}).then(function(meta) {
var forgeLevel = getForgeLevel(meta.item);
return getForgeMetadata(meta.character, meta.itemDesc, forgeLevel);
});
}
然而这坑爹货的代码还是一样的难读和难以维护啊,终于有一个人看不下去了,他就是 @赵颉,他把C#中的await语义移植到了js中,弄了个Wind.js出来,这样大家终于能写人话了:
function getForgeMetadata(cid, itemId) {
var character = $await(getCharacter(cid));
var item = $await(getItem(itemId));
var itemDesc = $await(getItemDesc(item.type));
var forgeLevel = getForgeLevel(item);
return $await(getForgeMetadata(character, itemDesc, forgeLevel));
}
然而顽固不化的Node.js社区断然拒绝了这绝妙的设计,老赵也停止了Wind.js的开发,最终版本的Wind.js也没加入只差一步的调试功能,我们刚进到蜜罐就又被迫迁移到promise上来,继续痛苦的旅程。

如果你认为这就是Node.js的唯一噩梦的话,你就太天真了。完全异步化带来的另一个问题就是调试困难。由于异步过程中的循环是利用回调来实现的,如果你恰好有个本地额缓存,然后缓存命中时就直接同步调用了回调函数,那么恭喜你,你会遇到栈溢出的问题(假设循环10000次,将会有10000*n的栈深度,想象一下吧),所以通常情况下,大家会采用setImmediate函数来调用回调函数,其结果是,发生错误时的栈信息可能是类似这样的:
Cannot call undefined
at onImmediate
(不准确,大概就这意思)
可是你该怎么知道是哪个坑爹的漏传了这个cb函数导致它是undefined?

除此之外,JavaScript设计上是非常不严谨的一门语言,导致有大量陷阱存在,你试着做做这里的题目就明白这玩意儿有多坑了。
http://javascript-puzzlers.herokuapp.com

Java
说完了JavaScript的部分,我们再来看看Java。Java的定义很简单,它是一种面向对象的静态语言。然而坑爹的sun(oracle)在java语言的成长之路上做出了一个又一个的错误决定,其中首当其冲的就是采用类型抹除的方式实现泛型,简单的说List<string>和List<WhatTheFuckClass>居然是同一个类型。
同样的Java也没有await语义的支持,所以你看到的Java程序通常情况下是同步的,基本上有2种方式,要嘛来一个请求,开一个线程,要嘛一个固定大小的线程池,请求在池中逐个执行,反正总归会有线程因为IO或者其他原因处在sleep状态,其结果就是没办法(很难)实现单服高并发的承载能力。
再者由于Java的表达力实在不怎么样,所以通常情况下Java代码又臭又长。

平台的对比
Node.js相对来说是一个比较优秀的平台,从很早的版本开始(记得是0.6还是0.8)就已经把npm作为默认组件打包在一起了。npm对于Node.js生态圈的意义在于,用户再也不需要手工管理依赖关系,对于刚开始使用的用户来说,也非常容易搭建起工作环境。你可以直接使用npm install package_name来安装包,也可以直接在package.json中声明,然后使用npm install来自动解析和安装依赖,这绝对是相对其他平台优秀很多的地方。
然后Node.js的执行环境有着不可避免的局限性,就是它终究是个单线程的执行环境,没法直接发挥多核、多CPU的服务器的优势。所以通常大型Node.js项目会采用多进程的架构(比如网易的pomelo,我们公司的游戏服务器也是类似的架构),而不同的进程间采用restful的接口进行通信,而这样的代价就是花费大量的CPU时间在JSON序列化和反序列化的过程中,总之就是坑啊。

Java的生态环境可以说是非常优秀,不可否认的,Java平台拥有这个世界上最完善的,而且是经过生产环境验证的工业级的库。不过由于设计上就是同步的语言,也没有C#中的await机制,整个平台都是同步的,对于高并发的环境来说,确实做起来会有一定的困难。

结论
1)Node.js和Java本身不产生竞争关系
2)他们谁也不会消亡,如果非要说谁更可能消亡的话,我觉得是Node.js
3)如果你要做的是小型项目,或者逻辑非常简单的项目,可以选择Node.js,因为开发、调试都很很快。
4)如果你要做的是逻辑简单,而并发大的项目,可以选择Node.js,它还是很适合左右游戏的聊天服务器,长连接消息推送服务器之类的项目的。
5)如果你在做一个大规模项目(5人以上协作),还是用C#吧,C#并不是跟Windows绑定的语言,非windows平台上的Mono也非常好用。

希望这洋洋洒洒的胡言乱语对你有用~
分享到:
评论

相关推荐

    node.js-study:Node.js研究

    Node.js 这是一个执行环境(JavaScript运行时),用于在Web浏览器以外的地方使用JavaScript,并在服务器环境中使用JavaScript。 支持大规模的网络应用程序开发。Node.js网络应用程序了解每个Node.js网络应用程序和...

    Node.JS第一章简介介绍

    Node.js是基于Chrome JavaScript运行时建立的一个平台,实际上它是对Google Chrome V8引擎进行了封装;该文档介绍从javascirpt、V8、优缺点、涉及领域、知识点,阐述了Node.js的开发涉及到领域和潜力。

    Node.js 对比 Python:优点、缺点和用例(csdn)————程序.pdf

    Node.js 对比 Python:优点、缺点和用例(csdn)————程序

    Node.js 多进程处理CPU密集任务的实现

    但缺点也很明显,由于 Node.js 是单线程程序,如果长时间运算,会导致 CPU 不能及时释放,所以并不适合 CPU 密集型应用。 当然,也不是没有办法解决这个问题。虽然 Node.js 不支持多线程,但是可创建多子进程来执行...

    极简MapReduce框架Mincemeat-node.zip

    Mincemeat-node 是使用Node.js实现的极简MapReduce框架,可以快速的部署投入工作,免去Hadoop繁琐的配置,享受随心大数据。Mincemeatpy实现的是一种非常简单的MapReduce模型,仅仅实现了任务的分布计算,并没有类似...

    Node.js 和 Python之间该选择哪个?

    最近,Node.js 和 Python 都因其广泛的特性和功能在市场上大受欢迎。在你开发Web应用程序的...用一种简单易懂的语言来说,Node.js是一个服务器端平台,它是在Google Chrome的JavaScript引擎(称为V8引擎)上开发的。Nod

    什么是Node.js?Node.js详细介绍

    主要介绍了什么是Node.js,Node.js能做什么,Node.js的优缺点,Node.js的例子等,需要的朋友可以参考下

    基于Node.Js的Markdown博客系统Liblog.zip

    Liblog是一个简单易用的Markdown博客系统,它是基于开源框架thinkJS(使用 ES6/7 特性开发 Node.js 框架)开发的nodejs项目 需要mysql数据库支持,具有管理后台功能,更新博客分为普通文章和markdown文章,markdown...

    浅析Node.js 中 Stream API 的使用

    本文由浅入深给大家介绍node.js stream api,具体详情请看下文吧。 基本介绍 在 Node.js 中,读取文件的方式有两种,一种是用 fs.readFile ,另外一种是利用 fs.createReadStream 来读取。 fs.readFile 对于每个 ...

    geotiff.js:geotiff.js是一个小型库,用于解析TIFF文件以进行可视化或分析。 它用纯JavaScript编写,可在浏览器和node.js应用程序中使用

    UInt1-31(有一些缺点) 浮动16/32/64 启用的压缩: 无压缩 打包位 左翼 放气(具有浮点或水平预测变量支持) JPEG格式 自动选择要阅读的概述级别 通过图像窗口或边界框和选定波段进行子设置 将样本读取到单独...

    Node.js配合node-http-proxy解决本地开发ajax跨域问题

    1. 后端接口打包到本地运行(缺点:每次后端更新都要去测试服下一个更新包,还要在本地搭建java运行环境,麻烦) 2. CORS跨域:后端接口在返回的时候,在header中加入’Access-Control-Allow-origin’:* 之类的(有...

    Node.js 的异步 IO 性能探讨

    Python 和 Ruby 也有这样的框架,但因为在实际使用中会不可避免地用到含有同步代码的库,因此没能成长起来,而在 Node.js 之前,JavaScript 的服务器端编程几乎是空白,所以 Node.js 才得以建立起了一个所有 IO 均为...

    cache_redis_node:在Redis,Mongo和Node.js中使用Cache的示例

    将缓存与Redis和Node.js结合使用 概括 快取 快取类型 客户端缓存(浏览器) Web服务器上的缓存 应用内缓存 在每种情况下缓存的优缺点 使用缓存即服务 雷迪斯 比较Redis和Memcached 安装和使用Redis和Node.js进行...

    magick-cli:适用于Node.js的本机ImageMagick CLI

    这是从节点开始使用某些库的好方法,但是存在以下缺点: 性能-与直接从Node.js环境中调用库C或C ++ API相比,对shell命令的调用花费更多的时间和更多的资源。 错误处理程序-有时您无法以正确的方式拦截和处理错误。...

    详解在Node.js中发起HTTP请求的5种方法

    在Node.js中有相当多的解决方案,其中有语言内置功能,也有开源社区贡献的开发库。下面咱们来看一下比较流行的几种方式。 在开始之前,请先在自己的计算机上安装最新版的node.js和npm。 HTTP – 标准库 首先是标准...

    node-configure:一个简单的用于node.js的多配置管理模块

    有几个可用于node.js的配置模块。 每种方法都有其优点和缺点,但是没有一个项目可以视为所有用例的最佳配置选项。 某些应用程序需要复杂的配置,可以从中央服务器获取。 其他人只想在应用启动时加载一个简单的JSON...

    新入门node.js必须要知道的概念(必看篇)

    一、对于一个刚入门node.js的朋友来说,一定要了解一些基础概念: 今年我正式进入社会后,发现自己所知道的IT方面的知识,真的只是牛毛,原来人外有人,山外有山,还需要继续努力。下面是一些我的自学习心得,发出来...

    node-event-storage:针对node.js的优化事件存储

    当前只有一个针对node / javascript的嵌入式事件存储实现,即https://github.com/adrai/node-eventstore 这是一个不错的项目,但是有一些缺点: 它的API完全基于事件流,因此,要提交新事件,首先需要检索完整的...

    markdownlint:用于MarkdownCommonMark文件的Node.js样式检查器和lint工具

    markdownlint 用于Markdown / CommonMark文件的Node.js样式检查器和lint工具。安装npm install markdownlint --save-dev总览标记语言旨在易于阅读,编写和理解。 它成功了-它的灵活性既是优点也是缺点。 可能有多种...

    Node.js编写组件的三种实现方式

    支持为python、lua、js等多种常见脚本语言生成C++组件包装代码,swig使用者只需要编写C++代码和swig配置文件即可开发各种脚本语言的C++组件,不需要了解各种脚本语言的组件开发框架,缺点是不支持javascript的回调,...

Global site tag (gtag.js) - Google Analytics