nodejs-07-事件循环

目录


nodejs 事件循环

nodejs 是单进程单线程的应用程序,

但是因为V8引擎提供了很多异步执行回调接口,

通过这些接口可以处理大量的并发,所以性能非常高。

nodejs 几乎每一个API都是支持回调函数的。

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

nodejs单线程,类似进入了一个 while(true)的事件循环,

直到没有事件观察者的时候,nodejs才推出。

每个异步事件,都生成一个事件观察者。如果有事件发生,就调用该回调函数。

nodejs和V8引擎,是什么关系?
事件机制 设计模式 观察者模式
事件 - 事件观察者 - 回调函数

首先回答第一个问题。
V8引擎,就是javascript的解释器,将js代码直译为机器码。
nodejs是一个平台,集成了V8引擎、事件循环和底层I/O应用编程接口


事件驱动程序

nodejs 使用事件驱动模型。

当web server接收到请求的时候,就把它关闭,然后进行处理,然后去服务下一个web请求。

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

这个模型,非常高效可扩展性也非常强。

因为webserver一直接受请求,而不等待任何读写操作。

这也称之为 非阻塞式IO 或者 事件驱动IO。

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

nodejs-07-事件循环

整个事件驱动的流程,就是这么实现的,非常简洁。

有点类似于观察者模式,事件相当于一个主题(subject),

而所有注册到这个事件上的处理函数,相当于观察者(observer)。

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

//引入events模块
var events = require('events');

//创建 eventEmitter对象
var eventEmitter = new events.EventEmitter();

以下程序绑定事件处理程序:

// 绑定事件及事件的处理程序
eventEmitter.on('eventName',eventHandler);

我们可以通过程序触发事件:

//触发事件
eventEmitter.emit('eventName');

实例

创建 main.js 文件,代码如下所示:

// 引入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('程序执行完毕。');

接下来让我们执行以上代码:

$ node main.js
连接成功。
数据接收成功。
程序执行完毕。

node应用程序是如何工作的?

在node应用程序中,执行异步操作的函数,将回调函数作为最后一个参数。

回调函数接收错误对象作为,第一个参数。

接下来,让我们来重新看下前面的实例,创建一个 input.txt 文件内容如下:

菜鸟教程官网地址: www.runoob.com

创建 main.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("程序执行完毕");

以上程序中,fs.readFile()是异步函数,用于读取文件。

如果在读取文件过程中发生错误,错误err对象就会输出错误信息。

如果没有发生错误,readFile跳过err对象的输出,文件内容就通过回调函数输出。

执行以上代码,执行结果如下:

程序执行完毕
菜鸟教程官网地址:www.runoob.com

接下来我们删除 input.txt文件,执行结果如下所示:

程序执行完毕
Error:ENOENT,open 'input.txt'

因为文件input.txt不存在,所以输出了错误信息。

上一篇:Nodejs 中的 EventEmitter是什么?


下一篇:Node.js核心入门