了解一些基本的概念
1.阻塞 I/O
程序执行的过程中会有很多的I/O操作,如读写文件,请求响应等等,而当读取一个文件, 整个流程都暂停下来,需要等待文件读取成功后才能进行下一步操作,也就是I/O操作阻塞了代码的执行,这样会极大的降低程序的效率。
下面举个例子让我们能够更好的理解一下阻塞I/O
var fs = require('fs');
var data = fs.readFileSync('data.txt');
console.log(data.toString());
console.log('程序执行结束~');
// 执行结果
我是data.txt中的内容
程序执行结束~
2.非阻塞 I/O
非阻塞I/O也就是指程序在执行的过程中,I/O操作不会阻塞程序的执行,也就是我在执行读取文件程序的同时不受影响,继续执行其他的代码(这主要得益于node的事件循环机制),很显让这种非阻塞I/O大大提高了程序的性能。
下面举个例子让我们能够更好的理解一下非阻塞I/O
var fs = require('fs');
fs.readFile('data.txt',function(err,data){
console.log(data.toString());
})
console.log('程序执行结束~');
// 执行结果
程序执行结束~
我是data.txt中的内容
3.node事件循环
Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。
Node.js 有很多 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发。
Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。
Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.
事件驱动程序:
理解node的事件驱动编程
Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件
// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);
// 触发事件
eventEmitter.emit('eventName');
下面我们就通过一个例子来看看events模块的用法
var events = require('events');
var eventEmitter = new events.EventEmitter();
eventEmitter.on('otherFn', function(){
console.log('i am otherFn');
eventEmitter.emit('callbackFn');
})
eventEmitter.on('callbackFn', function(){
console.log('i am callbackFn');
})
eventEmitter.emit('otherFn');
//执行结果
i am otherFn
i am callbackFn
综上:
我们可以将文章开始写的非阻塞I/O例子进行修改,即通过事件驱动获取数据
var fs = require('fs');
var events = require('events');
var eventEmitter = new events.EventEmitter();
fs.readFile('data.txt', function(err,data){
eventEmitter.emit('getData',data);
})
eventEmitter.on('getData',function(txt){
console.log(txt.toString());
})
// 执行结果
我是data.txt中的内容
参考: