← 返回目录

第 14 卷

第 14 / 19 卷日期:

4const emitter = new EventEmitter();

5 6// 异步操作函数

7function asyncOperation() { 8setTimeout(() => {

9emitter.emit("complete", "异步操作结果"); //触发完成事件
10}, 1000);
11 }

12 13// 监听完成事件

14emitter.on("complete", (data) => { 15console.log("后续逻辑:", data);

16});

17 18// 监听错误事件

19emitter.on("error", (err) => { 20console.error("错误:", err);
});

asyncOperation();

(3)Promise

ES6引入的异步编程规范,将异步操作封装为一个“Promise对象”,该对象代表异步操作的最终状态(成功/失败)和结果,通过链式调用替代嵌套回调。

• 特点:

  1. 解决回调地狱:通过 .then() 链式调用,将嵌套逻辑转为线性代码,可读性提升;
  2. 统一错误处理:通过 .catch() 可捕获链式调用中任意环节的错误,无需逐个处理;
  3. 状态不可逆:Promise有“pending(进行中)、fulfilled(成功)、rejected(失败)”三种状

态,状态一旦改变无法逆转;

  1. 支持并行/串行控制:通过 Promise.all()、 Promise.race() 等方法可方便控制多个异步

操作;

  1. 仍存在链式调用过长的问题(“then链”),代码冗余。

Code block

1 2// 示例:Promise实现异步读取文件

3const fs = require("fs/promises"); // Promise版本的fs模块 4fs.readFile("file1.txt", "utf8").then((data1) => {

(4)生成器(Generator)+ Promise

Generator是ES6引入的函数类型(函数名前加 *),支持暂停和恢复执行(通过 yield 关键字)。

结合Promise可实现异步操作的“同步化”书写,需配合自动执行器(如 co 库)使用。

• 特点:

  1. 异步逻辑同步化: yield 关键字可暂停函数执行,等待Promise完成后恢复,代码结构与同步代

码一致;

  1. 需要额外依赖自动执行器:原生Generator需手动调用 next() 方法恢复执行,实际开发中需使

用 co 库等自动执行工具;

  1. 错误处理灵活:可通过 try/catch 捕获 yield 表达式的错误;
  2. 相比Promise链式调用,代码更简洁,但理解成本较高。

Code block

1

2//示例:Generator + Promise + co库实现异步同步化
3const co = require("co");
4const fs = require("fs/promises");

5 6function* asyncGenerator() {

7try {

8const data1 = yield fs.readFile("file1.txt", "utf8"); //暂停等待Promise完成
9const data2 = yield fs.readFile("file2.txt", "utf8");
10console.log(data1 + data2);
11} catch (err) {
12console.error("错误:", err);
13}
14 }

15 16// co库自动执行Generator

17co(asyncGenerator());

(5)async/await

ES2017引入的异步编程语法糖,基于Promise实现,本质是Generator + 自动执行器的简化版。通过 async 关键字定义异步函数, await 关键字暂停函数执行,等待Promise完成后恢复。

• 特点:

  1. 错误处理直观:可直接使用 try/catch 捕获 await 表达式的错误,与同步代码的错误处理逻辑

一致;

  1. 完全基于Promise: async 函数的返回值是Promise对象,可与Promise的其他方法(如

Promise.all())配合使用;

  1. 兼容性:支持ES2017及以上环境,旧环境需通过Babel转译。

Code block

1 2// 示例:async/await实现异步读取文件

3const fs = require("fs/promises");

4 5async function asyncReadFile() {

6try {

7const data1 = await fs.readFile("file1.txt", "utf8"); //暂停等待Promise完成
8const data2 = await fs.readFile("file2.txt", "utf8");
9console.log(data1 + data2);
10} catch (err) {
11console.error("错误:", err);
12}
13 }

14 15asyncReadFile();

(6)总结

异步编程方案的演进趋势是“从繁琐到简洁、从嵌套到线性、从手动管理到自动执行”。实际开发中,优先使用async/await(简洁直观),配合Promise处理并行/串行异步操作;仅在兼容旧环境时

考虑回调函数或事件监听;Generator已基本被async/await替代,较少直接使用。

  1. 解释什么是回调函数,以及它在异步编程中的作用和存在的缺点。

(1)回调函数的定义

回调函数(Callback Function)是指作为参数传递给另一个函数的函数,且该函数会在另一个函数执行完成后(通常是异步操作完成后)被调用。简单来说,就是“把函数当作参数传递,让它在合适的

时机被执行”。

回调函数分为两种类型:

全站分卷索引 · 19 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷
  9. 9第 9 卷
  10. 10第 10 卷
  11. 11第 11 卷
  12. 12第 12 卷
  13. 13第 13 卷
  14. 14第 14 卷
  15. 15第 15 卷
  16. 16第 16 卷
  17. 17第 17 卷
  18. 18第 18 卷
  19. 19第 19 卷