官网上(http://www.nodejs.org )给Node下的定义是:”一个搭建在Chrome JavaScript 运行时上的平台,用于构建高速、可伸缩的网络程序。Node.js采用的事件驱动、非阻塞I/O模型,使它既轻量又高效,并成为构建运行在分布式设备上的数据密集型实时程序的完美选择“。

异步和事件触发:浏览器

Node为服务端JavaScript提供了一个事件驱动的、异步的平台,它是一个服务器端的JavaScript解释器。了解浏览器的工作原理对我们了解Node的工作原理会有很大帮助。它们都是事件驱动(用事件轮询)和非阻塞的I/O处理(用异步I/O)。下面举个例子说明这是什么意思。

我们来看一小段jQuery 用XMLHttpRequest(XHR)做Ajax 请求的代码:

$.post('/resource.json',function(data){//I/O不会阻塞执行console.log(data);
})
//脚本继续执行

这个程序会发送一个到resource.json的HTTP请求。当响应返回时会调用带着参数data的匿名函数(在这个上下文中的回调函数),data就是从那个请求中得到的数据。注意,代码没有写成下面这样:

var data=$.post('/resource.json');//在I/O完成之前程序会被阻塞
console.log(data);

在这个例子中,假定对resource.json的响应在准备好后会存储在变量data中,并且在此之前函数console.log 不会执行。I/O操作(Ajax 请求)会阻塞脚本继续执行,直到数据准备好。因为浏览器是单线程的,如果这个请求用了400ms 才返回,那么页面上的其他任何事件都要等到那之后才能执行。可以想象一下,如果一幅动画被停住了,或者用户试着跟页面交互时动不了,那种用户体验有多糟糕。理解JavaScript中的事件轮询

实际情况是,当浏览器中有I/O操作时,并且是用回调函数的方式写的。那么当这个I/O操作完成时,它会发出一个“事件”,然后这个事件会进入任务队列,等待CPU处理。

这个I/O是异步的,并且不会“阻塞”脚本执行,事件轮询仍然可以响应页面上执行的其他交互或请求。这样,浏览器可以对客户做出响应,并且可以处理页面上的很多交互动作。

异步和事件触发:服务器

可能大多数人都了解传统的服务器编程的I/O模型,下面是一个PHP的例子:

$result=mysql_query('select * from myTable');
print_r($result);

这段代码做了些I/O操作,并且在所有数据回来之前,这个进程会被阻塞。对于很多程序而言,这个模型没有什么问题,并且很容易理解。但有一点可能会被忽略:这个进程也有状态,或者说内存空间,并且在I/O完成之前基本上什么也不会做。根据I/O操作的延迟情况,那可能会有10ms到几分钟的时间。

对于服务器而言,当有更多的请求过来时,服务器通常会用多线程的方式,给每个连接分配一个线程。尽管这听起来是个很自然的委派服务器劳动力的方式,单程序内的线程管理会非常复杂。此外,当需要大量的线程处理很多并发的服务器连接时,线程会消耗额外的操作系统资源。线程需要CPU和额外的RAM来做上下文切换。

在Node中,I/O几乎总是在主事件轮询之外进行,使得服务器可以一直处于高效并且随时能够做出响应的状态。这样进程就更加不会受I/O限制,因为I/O延迟不会拖垮服务器,或者像在阻塞方式下那样占用很多资源。因此一些在服务器上曾经是重量级的操作,在Node服务器上仍然是可以轻量级的。

DIRT程序

实际上,Node所针对的应用程序有一个专门的简称:DIRT。它表示数据密集型实时(data-intensive real-time)程序。

var fs = require('fs');
fs.readFile('./resource.json',function(er,data){console.log(data);
});

这段程序要从硬盘里读取resource.json文件。读取文件是异步任务,我们可以继续处理其他任何操作,直到数据准备好。这个不是在浏览器中用jQurey发起的一个Ajax请求,而是在Node中访问文件系统抓取resource.json。

下面是一个简单的HTTP服务器实现,它会用“Hello Word”响应所有请求:

var http = require('http');
http.createServer(function(req,res){res.writeHead(200,{'Content-Type':'text/plain'});res.end('Hello World\n');
}).listen(3000);
console.log('Server running at http://localhost:300/');

只要有请求过来,它就会把“Hello World”写入到响应中返回。这个事件模型跟浏览器中对onclick事件的监听类似。下面是服务器的另一种写法,这样看起来request事件更明显:

var http = require('http');
var server = http.createServer();
server.on('request',function(req,res){res.writeHead(200,{'Content-Type':'text/plain'});res.end('Hello World\n');
})
server.listen(3000);
console.log('Server running at http://localhost:3000/');

Node在数据流和数据流动上也很强大。你可以把数据流看成特殊的数组,只不过数组中的数据分散在空间上,而数据流中的数据是分散在时间上的。下面我们用数据流的方式来处理resource.json

var stream = fs.createReadStream('./resource.json');
stream.on('data',function(chunk){console.log(chunk);
});
stream.on('end',function(){console.log('finished');
});

只要有新的数据块准备好,就会激发data事件,当所有数据块都加载完之后,会激发一个end事件。下面看看如何把一张图片留到客户端:

var http = require('http');
var fs = require('fs');
http.createServer(function(req,res){res.writeHead(200,{'Content-Type':'image/png'});fs.createReadStream('./image.png').pipe(res);
}).listen(3000);
console.log('Server running at http://localhost:3000/');

在这行代码中,数据从文件中读出来(fs.createReadStream),然后数据随着进来就被送到(.pipe)客户端(res)。在数据流动时,事件轮询还能处理其他事件。

欢迎进入Node.js世界相关推荐

  1. 要取代 Node.js 的 Deno 还活着吗?

    作者 | Fernando Doglio 译者 | 弯月 出品 | CSDN(ID:CSDNnews) 早在 2020 年 5 月,我就写了一篇介绍 Deno 的文章,后来还写了一本书.我喜欢 Den ...

  2. 我如何开始使用Node.js [关闭]

    有什么好的资源可以开始使用Node.JS? 有没有好的教程,博客或书籍? 当然,我已经访问了它的官方网站http://nodejs.org/ ,但是我认为他们拥有的文档不是一个很好的起点. #1楼 使 ...

  3. 为一个 iOS 应用编写一个简单的 Node.js/MongoDB Web 服务

    原文链接:https://github.com/nixzhu/dev-blog/blob/master/2014-04-21-write-a-simple-nodejs-mongodb-web-ser ...

  4. 【全文】狼叔:如何正确的学习Node.js

    说明 2017-12-14 我发了一篇文章<没用过Node.js,就别瞎逼逼>是因为有人在知乎上黑Node.js.那篇文章的反响还是相当不错的,甚至连著名的hax贺老都很认同,下班时读那篇 ...

  5. html js不触发_「万字整理 」这里有一份Node.js入门指南和实践,请注意查收 ??

    前言 什么是 Node.js 呢 ? JS 是脚本语言,脚本语言都需要一个解析器才能运行.对于写在 HTML 页面里的 JS,浏览器充当了解析器的角色.而对于需要独立运行的 JS,NodeJS 就是一 ...

  6. 狼叔:如何正确的学习Node.js

    1. [知乎Live]狼叔:如何正确的学习Node.js 预览地址 i5ting.github.io/How-to-lear- Live 简介 你好,我是 i5ting ,江湖人称「狼叔」,目前是阿里 ...

  7. 初学node.js有感二

    node.js进阶 一.回顾与继续   对于一种语言的认识都是经历这样的一个过程的,首先从原生的环境(CMD)中开始学习,找到一门语言之间各种引用的本质和相互之间的调用方式,明澈各种依赖关系,在这个基 ...

  8. node.js宣言(这个名字好霸气)

    http://cnodejs.org/topic/50b9ff94637ffa41554a87c5 引言:node.js 新兴的服务端技术,在很多公司已经开始悄然流行.是web server开发中解决 ...

  9. DockOne微信分享(六十九):微服务选型之Modern Node.js

    本文讲的是DockOne微信分享(六十九):微服务选型之Modern Node.js[编者的话]目前Node.js的发展非常快,大家可能还停留在:Node.js性能很好,Node.js里都是回调,写起 ...

最新文章

  1. c# 任务栏托盘图标鼠标进入MouseEnter和鼠标离开MouseLeave实现
  2. 02-CSS基础与进阶-day10_2018-09-14-20-38-10
  3. ASP.NET Core 优雅的在开发环境保存机密(User Secrets)
  4. 产品观念:更好的捕鼠器_故事很重要:为什么您需要成为更好的讲故事的人
  5. java使用Encoding导什么包_String getEncoding()
  6. 极速理解设计模式系列:4.原型模式(Prototype Pattern)
  7. Docker初识与安装
  8. MediaPlayer播放音频,也可以播放视频
  9. Logstash+Kibana+多ElasticSearch集群部署
  10. linux下部署tomcat的备忘
  11. 黑马程序员Git教程笔记
  12. 超详细!JDK 8 下载、安装和环境配置(macOS 和 Windows 版本)
  13. 中国移动 · 边缘计算技术白皮书 | PDF下载
  14. 很好用的搜网盘资源工具。很多都能找到
  15. 关于Chrome播放视频黑屏解决办法。
  16. 标题隐藏_经典街机游戏《三国志》,二十多年后你告诉我还有隐藏必杀
  17. 江苏大学和南京工业大学计算机哪个好,江苏大学和浙江大学,哪个好?
  18. android plc 课程,基于Android的智能PLC操控软件设计与实现
  19. 高德地图 天气预报查询
  20. Keil虚拟仿真逻辑仪和 真实逻辑仪(SaleaeLogic16)

热门文章

  1. 深信服副总裁张开翼:随需应变的IT新架构
  2. 【Java 新建项目】使用程序对新项目的各个实体 创建Dao、DaoImpl、Service、ServiceImpl层的文件...
  3. Android中的dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()
  4. CRUD之delete操作
  5. 岭南六少个人独立博客开通啦
  6. [zt]数学之美番外篇:平凡而又神奇的贝叶斯方法
  7. 4G EPS 的接口类型
  8. altium designer 原理图和PCB 多通道设计
  9. NR 5G NG-AP(NG接口)介绍
  10. 用Latex做介绍自己和团队科研的网页