目录
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。
在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时,触发回调函数。
整个事件驱动的流程,就是这么实现的,非常简洁。
有点类似于观察者模式,事件相当于一个主题(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不存在,所以输出了错误信息。