Node.js 回调函数和事件循环
Node.js 回调函数和事件循环
Lieme1. node.js 回调函数
node.js 的异步编程思想最直接的体现就是回调,在node中大量使用了回调函数,所有的API都支持回调函数,回调函数一般作为最后一个参数出现,正因为这样node在执行代码的时候就没有阻塞或者等待的操作,提高了node的性能,可以处理大量的并发请求。
function f1(name, age, callback){}
function f2(name, callback, callback2){}
阻塞代码实例
创建一个文件input.txt内容如下:
这是一个阻塞代码的实例
创建 node.js:
var fs = require('fs');
var data = fs.readFileSync('input.txt')
console.log(data.toString())
console.log('程序执行结束!')
结果如下:
这是一个阻塞代码的实例
程序执行结束!
如上:阻塞代码就是需要等待前面的代码执行完成后才能继续往后执行。
非阻塞代码实例
创建一个文件input.txt内容如下:
这是一个非阻塞代码的实例
创建 node.js:
var fs = require('fs')
fs.readFile('input.txt', function(err, data){
if (err) return console.log(err)
console.log(data.toString())
})
console.log('over')
结果如下:
over
这是一个阻塞代码的实例
如上,就是程序不必等到读取操作而直接执行后面的代码,等到读取完成后在执行读取文档的相关操作。
总结
阻塞是按顺序执行的,而非阻塞是不需要按照顺序的,需要处理的事件就写在回调函数之内即可。
node.js 事件循环
node.js 是单进程单线程应用程序,但是因为V8引擎提供的异步执行回调接口,通过这些接口可以处理大量并发,所以性能非常高,在nodejs中所有的事件机制都是用设计模式中观察者模式实现
node.js 单线程进入一个 while 的事件循环,知道没有事件观察者退出,每个异步事件都生成一个事件观察者,如果事件发生就调用该回调函数
node.js 事件驱动程序
node.js 使用事件驱动模型,当web server 接受到请求,就把它关闭然后处理,在去处理下一个web请求。当这个请求完成后,它会被放回到处理队列的开头,并将这个结果返回给用户。
node.js 的事件驱动扩展性非常强,因为web server一直在接受请求,而不进行任何等待操作,效率非常的高。整个流程类型观察者模式,事件相当于一个主题,所有注册到这个事件上的处理函数相当于观察者。
内置实例
// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
绑定事件:
// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);
触发事件:
// 触发事件
eventEmitter.emit('eventName');
实例
// 引入 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 应用程序如何工作
在 Node 应用程序中,执行异步操作的函数将回调函数作为最后一个参数, 回调函数接收错误对象作为第一个参数。
具体案例可以看上文的 非阻塞代码的实例:
正常执行结果就如上
如果把input.txt删除,那么就导致程序读取错误,就会走到代码的 err部分,就会出现如下结果:
over
Error: ENOENT, open 'input.txt'