回调函数
让我们看看在Node.js中如何用异步的方式读取一个文件,下面是一个列子
ps: 注意同文件夹下需要有first.txt文件 否则报错
var fs=require('fs');
//读取first.txt文件采用utf-8编码格式并设置一个匿名回调函数 fs.readFile('first.txt','utf-8',function(err,data) { if(err){ console.error(err); }else{ console.log(data); } }); console.log('end.'); //输出‘end.'
运行的结果如下:
end.
Contents of the file.
同步式读取文件的方式比较容易理解,将文件名作为参数传入fs.readFileSync 函
数,阻塞等待读取完成后,将文件的内容作为函数的返回值赋给 data 变量,接下来控制台
输出data 的值,最后输出end.。
异步式读取文件就稍微有些违反直觉了,end.先被输出。要想理解结果,我们必须先
知道在Node.js 中,异步式I/O 是通过回调函数来实现的。fs.readFile 接收了三个参数,
第一个是文件名,第二个是编码方式,第三个是一个函数,我们称这个函数为回调函数。
JavaScript 支持匿名的函数定义方式,譬如我们例子中回调函数的定义就是嵌套在
fs.readFile 的参数表中的。这种定义方式在JavaScript 程序中极为普遍,与下面这种定义
方式实现的功能是一致的:
//readfilecallback.js functionreadFileCallBack(err, data) { if(err) { console.error(err); } else{ console.log(data); } } varfs = require('fs'); fs.readFile('file.txt', 'utf-8', readFileCallBack); console.log('end.');
fs.readFile 调用时所做的工作只是将异步式I/O 请求发送给了操作系统,然后立即
返回并执行后面的语句,执行完以后进入事件循环监听事件。当fs 接收到I/O 请求完成的
事件时,事件循环会主动调用回调函数以完成后续工作。因此我们会先看到end.,再看到
file.txt 文件的内容
ps:Node.js中,并不是所有的API都提供了同步和异步版本。Node.js不鼓励使用同步I/O。
事件
Node.js所有的异步I/O操作在完成时都会发送一个事件在事件队列。事件由EventEmitter对象提供,前面提到的fs.readFile和http.createServer的回调函数都是通过EventEmitter来实现。下面通过一个简单的列子说明EventEmitter的用法:
//event.js var EventEmitter = require('events').EventEmitter; var event = new EventEmitter(); event.on('some_event',function() { console.log('some_event occured.'); }); setTimeout(function(){ event.emit('some_event'); },1000);
运行这段代码,1秒后控制台输出了some_event occured.。其原理是 event 对象注册了事件 some_event 的一个监听器,然后我们通过 setTimeout 在1000毫秒以后向
event 对象发送事件 some_event,此时会调用some_event 的监听器