Node.js开发指南(三)回调函数与事件

我就是我 2022-04-24 10:08 77阅读 0赞

让我们看看在 Node.js 中如何用异步的方式读取一个文件,下面是一个例子:

  1. //readfile.js
  2. var fs = require('fs');
  3. fs.readFile('file.txt', 'utf-8', function(err, data) {
  4. if (err) {
  5. console.error(err);
  6. } else {
  7. console.log(data);
  8. }
  9. });
  10. console.log('end.');

运行的结果如下:

  1. end.
  2. Contents of the file.

Node.js 也提供了同步读取文件的 API:

  1. //readfilesync.js
  2. var fs = require('fs');
  3. var data = fs.readFileSync('file.txt', 'utf-8');
  4. console.log(data);
  5. console.log('end.');

运行的结果与前面不同,如下所示:

  1. $ node readfilesync.js
  2. Contents of the file.
  3. end.
  4. 同步式读取文件的方式比较容易理解,将文件名作为参数传入 fs.readFileSync 数,阻塞等待读取完成后,将文件的内容作为函数的返回值赋给 data 变量,接下来控制台 输出 data 的值,最后输出 end.。
  5. 异步式读取文件就稍微有些违反直觉了,end.先被输出。要想理解结果,我们必须先 知道在 Node.js 中,异步式 I/O 是通过回调函数来实现的。fs.readFile 接收了三个参数, 第一个是文件名,第二个是编码方式,第三个是一个函数,我们称这个函数为回调函数。 JavaScript 支持匿名的函数定义方式,譬如我们例子中回调函数的定义就是嵌套fs.readFile 的参数表中的。这种定义方式在 JavaScript 程序中极为普遍,与下面这种定义 方式实现的功能是一致的:
  6. //readfilecallback.js
  7. function readFileCallBack(err, data) {
  8. if (err) {
  9. console.error(err);
  10. } else {
  11. console.log(data);
  12. }
  13. }
  14. var fs = require('fs');
  15. fs.readFile('file.txt', 'utf-8', readFileCallBack);
  16. console.log('end.');
  17. fs.readFile 调用时所做的工作只是将异步式 I/O 请求发送给了操作系统,然后立即 返回并执行后面的语句,执行完以后进入事件循环监听事件。当 fs 接收到 I/O 请求完成的 事件时,事件循环会主动调用回调函数以完成后续工作。因此我们会先看到 end.,再看到 file.txt 文件的内容。

Node.js 中,并不是所有的 API 都提供了同步和异步版本。Node.js 不 鼓励使用同步 I/O。

  1. Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。在开发者看来,事 件由 EventEmitter 对象提供。前面提到的 fs.readFile http.createServer 的回 调函数都是通过 EventEmitter 来实现的。下面我们用一个简单的例子说明 EventEmitter 的用法:
  2. //event.js
  3. var EventEmitter = require('events').EventEmitter;
  4. var event = new EventEmitter();
  5. event.on('some_event', function() {
  6. console.log('some_event occured.');
  7. });
  8. setTimeout(function() {
  9. event.emit('some_event');
  10. }, 1000);
  11. 运行这段代码,1秒后控制台输出了 some\_event occured.。其原理是 event 对象 注册了事件 some\_event 的一个监听器,然后我们通过 setTimeout 1000毫秒以后向 event 对象发送事件 some\_event,此时会调用 some\_event 的监听器。
  12. Node.js 的事件循环机制 Node.js 在什么时候会进入事件循环呢?答案是 Node.js 程序由事件循环开始,到事件循 环结束,所有的逻辑都是事件的回调函数,所以 Node.js 始终在事件循环中,程序入口就是 事件循环第一个事件的回调函数。事件的回调函数在执行的过程中,可能会发出 I/O 请求或 直接发射(emit)事件,执行完毕后再返回事件循环,事件循环会检查事件队列中有没有未 处理的事件,直到程序结束。图3-5说明了事件循环的原理。
  13. 与其他语言不同的是,Node.js 没有显式的事件循环,类似 Ruby EventMachine::run() 的函数在 Node.js 中是不存在的。Node.js 的事件循环对开发者不可见,由 libev 库实现。libev 支持多种类型的事件,如 ev\_ioev\_timerev\_signalev\_idle 等,在 Node.js 中均被 EventEmitter 封装。libev 事件循环的每一次迭代,在 Node.js 中就是一次 Ticklibev 断检查是否有活动的、可供检测的事件监听器,直到检测不到时才退出事件循环,进程结束。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3podW9nYW5saXdhbmppbg_size_16_color_FFFFFF_t_70

发表评论

表情:
评论列表 (有 0 条评论,77人围观)

还没有评论,来说两句吧...

相关阅读

    相关 函数

    回调与回调函数 回调 回调函数 回调   回调指的是某函数在执行的时候,由于某些原因,该函数被迫中止执行,交出当前线程的使用权,当前线程转而执行其它函