理解 JavaScript 中的 Iterator、Generator、Promise 与 async/await

Iterator 迭代器

在 JavaScript 中,数组、字符串、Map、Set 等都是可迭代对象。但如果你想要遍历一个自定义的数据结构(比如链表、树),没有内置遍历机制该怎么办?

这就是 迭代器模式 出现的原因 ------ 提供统一的访问接口,让不同的数据结构都可以被 for...of 遍历。

工作原理

  1. 创建一个指针对象,指向当前数据结构的起始位置
  2. 第一次调用next()方法,指针自动指向数据结构的第一个成员
  3. 每次调用next(),指针就往后移动
  4. 每次next(),返回一个对象{value,done}
    • value:当前成员值
    • done:是否遍历完成
js 复制代码
const arr = [10, 20, 30];
const it = arr[Symbol.iterator]();

console.log(it.next()); // { value: 10, done: false }
console.log(it.next()); // { value: 20, done: false }
console.log(it.next()); // { value: 30, done: false }
console.log(it.next()); // { value: undefined, done: true }

本质

  • 把遍历逻辑抽象成一个接口
  • 内部维护当前位置,每次调用next()更新状态

手写迭代器

js 复制代码
function createIterator(arr) {
  let index = 0;
  return {
    next() {
      if (index < arr.length) {
        return { value: arr[index++], done: false };
      } else {
        return { value: undefined, done: true };
      }
    }
  };
}

const it = createIterator([1, 2, 3]);
console.log(it.next()); // { value: 1, done: false }
console.log(it.next()); // { value: 2, done: false }
console.log(it.next()); // { value: 3, done: false }
console.log(it.next()); // { value: undefined, done: true }

Generator 生成器

Generator 是 特殊的函数 ,用 function* 定义,执行时可以被"暂停"和"恢复"。

工作原理

  • 调用function*定义的函数,不会立即执行,而是返回一个迭代器对象
  • 调用next(),函数执行到yeild暂停,并返回对应的值
  • 下次执行next(),会接着上次暂停处继续
  • 可以通过next(value)把值传回函数内部
  • 直到函数结束,返回{value:undefined,done:true}
js 复制代码
function* gen() {
  yield 1;
  yield 2;
  yield 3;
}
const it = gen();

console.log(it.next()); // { value: 1, done: false }
console.log(it.next()); // { value: 2, done: false }
console.log(it.next()); // { value: 3, done: false }
console.log(it.next()); // { value: undefined, done: true }

本质

  • 是迭代协议的语法糖
  • 内部是一个状态机,能在不同状态间来回切换
  • 支持协程风格的异步编程(后来async/await取代了它)

Promise

为什么需要Promise?

  • 解决回调地狱
  • 提供统一的异步 API (then/catch/finally)
  • 可链式调用,错误统一处理

工作原理

  • 创建时立即执行 executor(resolve, reject)
  • 内部维护三种状态
    • pending
    • fulfilled
    • rejected
  • 状态发生变化就不可逆
  • 调用then/catch方法,回调会放入微任务队列,在事件循环末端执行
js 复制代码
const p = new Promise((resolve, reject) => {
  setTimeout(() => resolve("ok"), 1000);
});

p.then(res => console.log(res)); // 1秒后打印 "ok"

本质

  • 状态机 + 异步任务调度器

  • 把异步结果抽象成一个"可组合的值";

  • 避免了传统回调地狱。

async/await

为什么需要async/await?

  • Promise 链虽然解决了回调地狱,但可读性仍差
  • async/await 可以写出 同步风格异步代码
  • 错误处理更简单(try/catch)

工作原理

  • async function调用后,始终返回一个Promise
  • 执行遇到await时
    • 表达式立即执行
    • 如果是普通值,转成 Promise.resolve(value)
    • 如果是promise,暂停函数执行,等待结果
  • 等 Promise 完成后,恢复执行,并把结果返回给 await 表达式
  • 如果Promise失败,抛出错误,可以使用try...catch捕获
js 复制代码
async function getData() {
  const res = await new Promise(resolve => setTimeout(() => resolve("ok"), 1000));
  console.log(res); // "ok"
}
getData();

本质

  • Generator + Promise 的语法糖
  • Babel 转译 async/await → Generator
  • 让异步代码看起来像同步,更易读易维护

babel转译原理

js 复制代码
async function fetchData() {
  const a = await getA();
  const b = await getB(a);
  return b;
}

// 转译等价于
function fetchData() {
  return _asyncToGenerator(function* () {
    const a = yield getA();
    const b = yield getB(a);
    return b;
  })();
}

function _asyncToGenerator(genFn) {
  return function() {
    const gen = genFn.apply(this, arguments);
    return new Promise((resolve, reject) => {
      function step(key, arg) {
        let info;
        try { info = gen[key](arg); } 
        catch (err) { return reject(err); }
        if (info.done) resolve(info.value);
        else Promise.resolve(info.value)
          .then(val => step("next", val), err => step("throw", err));
      }
      step("next");
    });
  }
}
相关推荐
jinmo_C++几秒前
从零开始学前端 · HTML 基础篇(一):认识 HTML 与页面结构
前端·html·状态模式
鹏多多6 分钟前
前端2025年终总结:借着AI做大做强再创辉煌
前端·javascript
小Tomkk15 分钟前
⭐️ StarRocks Web 使用介绍与实战指南
前端·ffmpeg
不一样的少年_19 分钟前
产品催: 1 天优化 Vue 官网 SEO?我用这个插件半天搞定(不重构 Nuxt)
前端·javascript·vue.js
-dcr20 分钟前
50.智能体
前端·javascript·人工智能·ai·easyui
行者9630 分钟前
Flutter跨平台开发适配OpenHarmony:进度条组件的深度实践
开发语言·前端·flutter·harmonyos·鸿蒙
云和数据.ChenGuang31 分钟前
Uvicorn 是 **Python 生态中用于运行异步 Web 应用的 ASGI 服务器**
服务器·前端·人工智能·python·机器学习
IT_陈寒33 分钟前
SpringBoot 3.0实战:这5个新特性让你的开发效率提升50%
前端·人工智能·后端
遗憾随她而去.41 分钟前
Webpack 面试题
前端·webpack·node.js
a程序小傲42 分钟前
得物Java面试被问:边缘计算的数据同步和计算卸载
java·开发语言·数据库·后端·面试·golang·边缘计算