- 浏览: 1612584 次
- 性别:
- 来自: 厦门
文章分类
- 全部博客 (603)
- T_java (145)
- T_script&ASP (51)
- T_C/C++ (25)
- T_PowerBuilder (11)
- T_Database (53)
- T_odoo (7)
- T_应用服务器 (50)
- T_专_条形码 (6)
- T_专_负载均衡器 (4)
- T_操作系统 (94)
- T_信息安全 (41)
- T_专_搜索引擎 (14)
- T_L_PHP (58)
- T_L_Delphi (18)
- T_L_.NET、C#、VisualStudio (25)
- T_L_Objective-C (6)
- T_移动开发 (53)
- T_网络 (109)
- T_大数据 (2)
- T_嵌入式 (2)
- T_小众技术 (24)
- T_未分类 (58)
- L_旅游印记 (1)
- L_生活随笔 (48)
- L_中国文化 (18)
- L_户外与生存 (0)
最新评论
-
csbean4004:
不知道哪传来得恶习,发帖子不好好发,故意弄错一些东西,很讨厌
让HTML5支持后置摄像头 -
withthewind:
终于找到一个可以用的了。。。
如何用VBA取得Word文档中的标题前面的序号 -
busbby:
兄弟,无法下载,说文件不完整
一个好用的Outlook ost格式文件转pst文件的工具 -
yijavakevin:
密码啊~解压密码多少?
一个二维条形码组件 -
vipbooks:
你给的那个链接根本无法下载,跳到官网看了下最新版12M,但点下 ...
十步以内完成精细web打印
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也非常好用。
希望这洋洋洒洒的胡言乱语对你有用~
计算机语言和技术平台很多时候不是谁更好谁更差的问题,而是谁更合适的问题,这里我们从语言和生态系统两个维度来坐下简要的对比。
语言的对比
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也非常好用。
希望这洋洋洒洒的胡言乱语对你有用~
发表评论
-
SpringBoot Fat Jar解压运行
2018-06-28 21:40 2263SpringBoot已经成为当前最流行的微服务 ... -
一句话实现五星评分显示
2018-06-05 08:31 999Python: rate = 1 #rate 取值 ... -
来算google的可视化编程工具——Blockly,不仅仅是玩具
2017-10-16 21:34 33161Blockly - 来自Google的可 ... -
安卓动态分析工具 Inspeckage
2017-08-07 08:46 0工具介绍 一个基于Xposed 开发的应用动态分析工具 g ... -
Android逆向之旅---静态方式破解微信获取聊天记录和通讯录信息
2017-08-07 08:37 0一、猜想数据存放路径 微信现在是老少皆宜,大街小巷都在使用 ... -
破解微信数据库 并查询数据上传服务器
2017-08-07 08:29 0由于工作需求破解了微信的数据库 并获取想要的信息上传服 ... -
安卓黑科技之HOOK详解
2017-08-07 08:21 0本文带大家进入到安卓另一个世界 互联网攻防大战 Xpos ... -
安卓逆向之基于Xposed-ZjDroid脱壳
2017-08-07 08:18 0前言 之前介绍了普通常见的反编译模式 但对于使用了 360 ... -
十步以内完成精细web打印
2017-06-21 11:44 7389注意: 康虎云报表组 ... -
pdf2htmlEX:把PDF转换成HTML的神器
2017-03-15 19:00 2776pdf2htmlEX:将 PDF 转为 HTML 网页 反 ... -
子div撑不开父div的几种解决方法
2017-02-26 11:39 2872子div撑不开父div的几种解决方法 子div撑不开 ... -
浏览器端精准打印或套打组件
2017-01-18 13:05 6704注意: 康虎云报表 ... -
让ie6 7 8 9支持html5 websocket
2016-12-23 20:52 2322结果: 从github上的 web ... -
如何让三列div中间那个自适应宽度
2016-12-03 18:46 721效果如图: 直接上代码,具体看注释: < ... -
两个相同放大镜叠加焦距计算
2016-09-16 19:47 2424关于两个相同放大镜叠加后焦距的计算公式: F={ ( f ... -
疯狂软件对Oracle放弃Java EE的看法
2016-08-14 22:38 530来源:http://javaligang ... -
Windown下最简安装nodejs和npm
2016-06-20 21:03 688Windown下最简安装nodejs和npm 一、下 ... -
几个Java相关的思维导图
2016-03-17 13:07 961来源:http://blog.csdn.net/jackf ... -
八款优秀的Linux天文学软件
2016-02-21 20:31 2913八款优秀的Linux天文学软件 天文学是一门研究恒 ... -
jasperReport Applet 打印
2016-02-01 16:33 873Applet方式的原理是本地下载Applet以及Jas ...
相关推荐
Node.js 的缺点包括: * 学习曲线陡峭: Node.js 的异步机制和事件驱动机制需要开发者具备一定的编程基础和经验。 * 不适合计算密集型应用程序: Node.js 不适合计算密集型应用程序,因为它的单线程模型限制了其...
Node.js 的缺点是需要编写代码来实现服务器的功能,需要学习 Node.js 的技术特点和编程模型。 Node.js 是一个服务器程序,旨在提供一种简单的构建可伸缩网络程序的方法。 Node.js 解决了服务器能够处理的并发连接...
- 分析Node.js内部的工作原理,特别是事件循环机制是如何工作的。 - 讨论事件循环对程序性能的重要性及常见问题解决方法。 - **流(Streams):** - 介绍Node.js中的流概念,包括可读流、可写流、双向流等。 - ...
标题 "Node.js-require-node在前端require后端javascript代码并调用" 涉及到的是将Node.js的模块系统引入到前端JavaScript中,以便在浏览器环境中使用原本只能在Node.js后端运行的代码。这一技术的核心是`require-...
Ansible 部署 Node.js Ansible 是一款自动化部署工具,可以帮助开发者快速部署 Node.js 应用程序。在 CentOS6.x 服务器上部署 Node.js 可以使用 Ansible playbook 来实现。下面是具体的实现步骤: 1. 添加额外的...
该项目是一个基于Vue.js、Node.js和MySQL数据库的校园二手交易网站,主要面向大学生...通过完成此项目,开发者不仅能熟练掌握Vue.js、Node.js和MySQL的使用,还能了解SPA架构的优缺点,以及如何构建一个完整的Web应用。
Node.js 提供了多种事件驱动编程模型,如回调函数、 promise 和 async/await 等,每种模型都有其优缺点。 构建完整的 web 应用 ------------------- 本书带领读者一步一步地完成一个完整的 web 应用,包括创建...
Node.js由Ryan Dahl在2009年发布,基于Google的V8 JavaScript引擎,用于处理网络请求和响应,无需传统服务器如Apache或Ngix。 PHP是世界上最流行的服务器端语言之一,由于其简单易学和对Web开发的广泛支持,PHP被...
Node.js是一种基于Chrome V8引擎的JavaScript运行环境,它使得JavaScript可以在服务器端运行,从而打破了JavaScript只能在浏览器中执行的传统。描述中的“用node.js开发网站”进一步确认了这是关于如何使用Node.js...
Node.js 是一种流行的开源后端 JavaScript 运行环境,它使用 Google 的 V8 JavaScript 引擎来执行服务器端的 JavaScript。本书旨在帮助读者从零开始掌握 Node.js 的基础知识,并能够实际编写出功能完备的应用程序。 ...
Node.js是一种轻量级的服务器端JavaScript环境,它基于Chrome V8引擎,具有事件驱动、非阻塞I/O的特性。Node.js广泛应用于构建高性能、可扩展的网络应用,尤其是在I/O密集型的场景下,如实时消息推送、聊天室、协作...
相比之下,Node.js 是基于 JavaScript 的后端开发平台,以其非阻塞I/O和事件驱动模型而闻名。这使得Node.js在处理大量并发请求时表现出色,特别适合构建实时应用和高流量的Web服务。Node.js 的 V8 引擎提供了一流的...
Node.js从入门到精通知识分享 本资源摘要提供了 Node.js 从入门到精通的知识分享,涵盖了 Node.js 的基础知识、 Express 框架、 MongoDB 数据库、 RESTful API 架构、前后端交互、Cookie 和 Session 验证、MVC 架构...
Node.js 是一个强大的开源开发平台,它基于 Google 的高性能 V8 JavaScript 引擎,使得 JavaScript 能够在服务器端运行,不再局限于浏览器环境。这个技术的出现极大地拓展了 JavaScript 的应用范围,使得开发者可以...
Node.js是一种基于Chrome V8引擎的JavaScript运行环境,它允许开发者在服务器端使用JavaScript进行编程,从而打破了JavaScript只能在浏览器中运行的传统。Node.js利用非阻塞I/O和事件驱动模型,使其在处理高并发请求...
为了适应现代人类强烈的时间观念,对于二手书交易传统管理方式的缺点,互联网的出现打破了这种局限性,给了广大用户更大的选择空间,促进了基于Node.js的二手书交易平台系统,有效的避免了二手书交易管理缭乱的局面...
Node.js 这是一个执行环境(JavaScript运行时),用于在Web浏览器以外的地方使用JavaScript,并在服务器环境中使用JavaScript。 支持大规模的网络应用程序开发。Node.js网络应用程序了解每个Node.js网络应用程序和...
### Node.js 安装第三方控件的三种方式 在Node.js开发过程中,使用第三方库或模块(也称为“控件”)是极为常见的做法。这些第三方控件可以帮助开发者快速实现功能,提高开发效率。根据提供的文件信息,我们将详细...