深入浅析Node.js 事件循环

Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。

(来源于Javascript是单线程又是异步的,但是这种语言有个共同的特点:它们是 event-driven 的。驱动它们的 event 来自一个异构的平台。)

Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发。

Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。

Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.

事件驱动模型

Node.js 使用事件驱动模型,当webserver接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。

当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。

这个模型非常高效可扩展性非常强,因为webserver一直接受请求而不等待任何读写操作。
(这也被称之为非阻塞式IO或者事件驱动IO)

在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。

整个事件驱动的流程就是这么实现的,非常简洁。有点类似于观察者模式,事件相当于一个主题(Subject),而所有注册到这个事件上的处理函数相当于观察者(Observer)。

Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件,如下实例:

//引入events模块
var events = require('events');
//创建eventEmitter对象
var eventEmitter = new events.EventEmitter();
//创建事件处理程序
var connectHandler = function connected() {
 console.log('连接成功。');
 //触发data_received事件
 eventEmitter.emit('data_received');
}
//绑定connection事件处理程序
eventEmitter.on('connection', connectHandler);
//使用匿名函数绑定data_received事件
eventEmitter.on('data_received', function(){
 console.log('数据接收成功。');
});
//触发connection事件
eventEmitter.emit('connection');
console.log("程序执行完毕。"); 

以上代码输出的结果是:

连接成功。

数据接收成功。

程序执行完毕。

上述的结果正如你想的一样,通过这种事件驱动模型我们就可以实现异步操作的。

(例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js 的性能,可以处理大量的并发请求。)

var fs = require("fs");
fs.readFile('input.txt', function (err, data) {
 if (err){
 console.log(err.stack);
 return;
 }
 console.log(data.toString());
});
console.log("程序执行完毕。"); 

以上代码输出的结果是:

程序执行完毕。

input.txt的内容。

从上述代码可以看出fs.readFile可以分发事件,当然Node.js里面的许多对象都会分发事件,一个net.Server对象会在每次有新连接时也会分发一个事件, 所有这些产生事件的对象都是 events.EventEmitter 的实例。

不过大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。

为什么要这样做呢?原因有两点:

首先,具有某个实体功能的对象实现事件符合语义, 事件的监听和发射应该是一个对象的方法。
其次 JavaScript 的对象机制是基于原型的,支持 部分多重继承,继承 EventEmitter 不会打乱对象原有的继承关系。

下面给大家分享我的第一个NodeJs项目

Node.js的安装通常有两种方式:自己编译源代码和使用编译好的文件,我这里使用编译好的文件
目前我的home目录下有刚下载来的node-v4.2.3-linux-x64

1.首先解压缩

代码如下:

tar xvf node-v4.2.3-linux-x64

2.设置链接,设置链接的目的在于任何路径都能够用到node命令

代码如下:

ln -s /home/node-v4.2.3-linux-x64/bin/node /usr/local/bin/node
ln -s /home/node-v4.2.3-linux-x64/bin/npm /usr/local/bin/npm

3.在home文件夹下建个目录叫mynodeproj,然后再建了个文件叫server.js(当然也可以起别的名字)

var http = require('http');
http.createServer(function (request, response) {
 //发送 HTTP 头部
 //HTTP 状态值: 200 : OK
 //内容类型: text/plain
 response.writeHead(200, {'Content-Type': 'text/plain'});
 //发送响应数据 "Hello World"
 response.end('Hello World\n');
}).listen(8888);
//终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/'); 

4.使用node命令执行以上代码

node server.js

执行上述命令之后会在命令行中显示"Server runnint at http://127.0.0.1:8888/",这样表示程序已经执行成功了!

因为我这个服务器是在阿里云里跑起来的,所以只要在外面的浏览器中键入阿里云IP+端口就可以访问了。

时间: 2015-12-17

深入理解Node.js 事件循环和回调函数

本文详细的介绍了Node.js 事件循环和Node.js回调函数,废话不多说了,具体看下面把.  一.Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高.Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发.Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现.Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观

Node.js 事件循环详解及实例

 Node.js  事件循环详解及实例 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发. Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现. Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数. Node.js 有多个内置的事件,我们可以

Node.js事件循环(Event Loop)和线程池详解

Node的"事件循环"(Event Loop)是它能够处理大并发.高吞吐量的核心.这是最神奇的地方,据此Node.js基本上可以理解成"单线程",同时还允许在后台处理任意的操作.这篇文章将阐明事件循环是如何工作的,你也可以感受到它的神奇. 事件驱动编程 理解事件循环,首先要理解事件驱动编程(Event Driven Programming).它出现在1960年.如今,事件驱动编程在UI编程中大量使用.JavaScript的一个主要用途是与DOM交互,所以使用基于事件

小结Node.js中非阻塞IO和事件循环

学习和使用Node.js已经有两个月,使用express结合mongoose写了一个web应用和一套RESTful web api,回过头来看Node.js官网首页对Node.js的介绍:Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.那么其中的non-blocking I/O model 意味着什么呢? 非阻塞的IO模型 首先,IO操作无疑是耗时的,当服务器

我的Node.js学习之路(三)--node.js作用、回调、同步和异步代码 以及事件循环

一,node.js的作用, I/O的意义,(I/O是输入/输出的简写,如:键盘敲入文本,输入,屏幕上看到文本显示输出.鼠标移动,在屏幕上看到鼠标的移动.终端的输入,和看到的输出.等等)   node.js想解决的问题,(处理输入,输入,高并发 .如 在线游戏中可能会有上百万个游戏者,则有上百万的输入等等)(node.js适合的范畴:当应用程序需要在网络上发送和接收数据时Node.js最为适合.这可能是第三方的API,联网设备或者浏览器与服务器之间的实时通信)   并发的意义,(并发这个术语描述的

JavaScript事件学习小结(三)js事件对象

相关阅读: JavaScript事件学习小结(五)js中事件类型之鼠标事件 http://www.jb51.net/article/86259.htm JavaScript事件学习小结(一)事件流 http://www.jb51.net/article/86261.htm javaScript事件学习小结(四)event的公共成员(属性和方法) http://www.jb51.net/article/86262.htm JavaScript事件学习小结(二)js事件处理程序 http://www

我的Node.js学习之路(二)NPM模块管理

NPM是一个Node包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准.有了NPM,可以很快的找到特定服务要使用的包,进行下载.安装以及管理已经安装的包. NPM常用的命令有: (1)$ npm install moduleNames                安装Node模块                注意事项:如果在使用模块的时候不知道其名字,可以通过http://search.npmjs.org网站按照                                

浅谈Node 异步IO和事件循环

前言 学习Node就绕不开异步IO, 异步IO又与事件循环息息相关, 而关于这一块一直没有仔细去了解整理过, 刚好最近在做项目的时候, 有了一些思考就记录了下来, 希望能尽量将这一块的知识整理清楚, 如有错误, 请指点轻喷~~ 一些概念  同步异步 & 阻塞非阻塞 查阅资料的时候, 发现很多人都对 异步和非阻塞 的概念有点混淆, 其实两者是完全不同的, 同步异步指的是 行为即两者之间的关系 , 而阻塞非阻塞指的是 状态即某一方 . 以前端请求为一个例子,下面的代码很多人都应该写过 $.ajax(

我的Node.js学习之路(四)--单元测试

通过NPM安装: npm install nodeunit -g 支持命令行,浏览器运行. 各种断言. 在node.js下模块化对于方法导出exports, 如果是对象导出module.exports,模块儿是单元测试的基础,看下面的node.js代码: var fs = require('fs'), global=require('./global.js'); var utils = { startWith: function(s1, s) { if (s == null || s == "&

我的Node.js学习之路(一)

一,node.js介绍   这些网上一大堆信息,我只精简 1,什么是node.js 从核心上说:Node.js是个事件驱动的服务器端javascript环境,也就是说,我们可以像使用PHP,Ruby和Python语言那样,使用javascript创建服务器端的应用程序.对于网络以及创建与网络交互的软件,它尤为专注. 2,使用Node.js能做什么 它既可以创建对文件系统进行操作的小段脚本,也可以创建大规模的Web应用程序来运行整个业务.由于Node.js的独特设计,他非常适合于多人游戏,实时系统

js 学习笔记(三)

一种面向对象语言需要向开发者提供四种基本能力: (1) 封装--把相关的信息(无论数据或方法)存储在对象中的能力. (2) 聚集--把一个对象存储在另一个对象内的能力. (3) 继承--由另一个类(或多个类)得来类的属性和方法的能力. (4) 多态--编写能以多种方法运行的函数或方法的能力. 对象的类型 1.本地对象 ①Array类 ②Date类 2.内置对象 3.宿主对象 Array类 toString()方法和valueOf()方法,返回特殊的字符串.该字符串是通过对每项调用toString

C# 委托的三种调用示例(同步调用 异步调用 异步回调)

首先,通过代码定义一个委托和下面三个示例将要调用的方法: 复制代码 代码如下: public delegate int AddHandler(int a,int b);    public class 加法类    {        public static int Add(int a, int b)        {            Console.WriteLine("开始计算:" + a + "+" + b);            Thread.Sl

Node.js学习之TCP/IP数据通讯(实例讲解)

1.使用net模块实现基于TCP的数据通讯 提供了一个net模块,专用于实现TCP服务器与TCP客户端之间的通信 1.1创建TCP服务器 在Node.js利用net模块创建TCP服务器 var server = net.createServer([options],[connectionListener]) //options:false当TCP服务器接收到客户端发送的一个FIN包时将会回发一个FIN包 true当TCP服务器接收到客户端发送的一个FIN包时将不会回发FIN包,这使得TCP服务器

Node.js学习教程之Module模块

前言 采用了 Commonjs 规范,通过 module.exports.require 来导出和导入模块.模块加载机制中,采用了延迟加载的策略.就是说在用到的情况下,系统模块才会被加载,等加载完成后会放到 binding_cache 中. 分类(模块类型) 系统模块 核心模块(native 模块),http.buffer.fs 等,底层调用的内建模块 (C/C++): C/C++ 模块(built-in 内建模块),供 native 模块调用: 第三方模块 第三方维护的模块,比如 expres