Promise、Generator和Async的差异是什么

发布时间:2022-02-09 11:16:59 作者:iii
来源:亿速云 阅读:164
# Promise、Generator和Async的差异是什么

## 目录
1. [引言](#引言)
2. [JavaScript异步编程演进](#javascript异步编程演进)
3. [Promise核心机制](#promise核心机制)
4. [Generator工作原理](#generator工作原理)
5. [Async/Await本质剖析](#asyncawait本质剖析)
6. [三者的横向对比](#三者的横向对比)
7. [性能与调试差异](#性能与调试差异)
8. [最佳实践场景](#最佳实践场景)
9. [总结](#总结)

## 引言
在现代JavaScript开发中,异步编程是处理I/O操作、网络请求等非阻塞任务的核心范式。从回调地狱到Promise链式调用,再到Generator的协程方案,最终演化为Async/Await语法糖,JavaScript的异步解决方案经历了数次重大革新。本文将深入解析这三种技术的实现原理、适用场景及本质差异。

## JavaScript异步编程演进
### 回调函数时代
```javascript
fs.readFile('file1.txt', (err, data) => {
  if (err) throw err;
  fs.readFile('file2.txt', (err, data2) => {
    // 回调地狱典型结构
  });
});

Promise革命

readFilePromise('file1.txt')
  .then(data => readFilePromise('file2.txt'))
  .catch(err => console.error(err));

Generator突破

function* readFiles() {
  const data1 = yield readFilePromise('file1.txt');
  const data2 = yield readFilePromise('file2.txt');
}

Async/Await终极方案

async function readFiles() {
  const data1 = await readFilePromise('file1.txt');
  const data2 = await readFilePromise('file2.txt');
}

Promise核心机制

状态机模型

stateDiagram
    [*] --> Pending
    Pending --> Fulfilled: resolve()
    Pending --> Rejected: reject()

核心特性

  1. 不可逆状态:一旦fulfilled/rejected不可逆转
  2. 微任务队列.then()回调进入微任务队列
  3. 链式调用:每个.then()返回新Promise

典型问题

// 常见的Promise误区
new Promise((resolve) => {
  resolve(1);
  console.log(2); // 仍然会执行
}).then(console.log);
// 输出顺序:2 → 1

Generator工作原理

可中断执行的函数

function* gen() {
  yield 1;
  yield 2;
  return 3;
}
const g = gen();
g.next(); // {value: 1, done: false}

协程实现原理

  1. 执行权移交:通过yield暂停执行
  2. 双向通信next(value)可传入值
  3. 异常处理throw()方法注入错误

自动执行器示例

function runGenerator(genFunc) {
  const gen = genFunc();
  function step(nextFn) {
    const next = nextFn();
    if (!next.done) {
      Promise.resolve(next.value).then(
        v => step(() => gen.next(v)),
        e => step(() => gen.throw(e))
      );
    }
  }
  step(() => gen.next());
}

Async/Await本质剖析

语法糖的真相

// async函数等价形式
async function foo() {}
// 等同于
function foo() {
  return new Promise((resolve) => {
    resolve();
  });
}

关键差异点

特性 Async函数 Generator
返回值 Promise Iterator
执行方式 自动执行 需手动触发
错误处理 try/catch 外部throw()

V8引擎实现

三者的横向对比

控制流比较

flowchart TD
    A[Promise] -->|链式调用| B[.then()]
    C[Generator] -->|yield暂停| D[外部控制]
    E[Async] -->|await等待| F[隐式Promise]

转换关系

// Promise → Generator
function* promiseToGen(promise) {
  return yield promise;
}

// Generator → Async
async function genToAsync(genFunc) {
  return await runGenerator(genFunc);
}

错误处理对比

// Promise
fetch().catch(handleError);

// Generator
try {
  iterator.throw(new Error());
} catch (e) {}

// Async/Await
try {
  await fetch();
} catch (e) {}

性能与调试差异

V8性能分析

  1. Promise

    • 微任务队列开销
    • 多级链式调用内存占用
  2. Generator

    • 上下文切换成本
    • 手动执行器额外开销
  3. Async/Await

    • 最优化的代码路径
    • 最小化上下文保存

调试体验

// Async函数的调试优势
async function debugExample() {
  const a = await step1(); // 断点可停在await之后
  const b = await step2(a);
  return b;
}

最佳实践场景

适用场景矩阵

方案 I/O密集型 CPU密集型 复杂流程控制
回调函数
Promise ⚠️
Generator ⚠️
Async/Await ⚠️

混合使用模式

async function* paginatedFetch(url) {
  let page = 1;
  while (true) {
    const res = await fetch(`${url}?page=${page}`);
    yield res.json();
    if (!res.hasNext) break;
    page++;
  }
}

// 使用示例
for await (const data of paginatedFetch('/api')) {
  process(data);
}

总结

  1. 演化脉络:回调 → Promise → Generator → Async/Await
  2. 核心差异
    • Promise:值/状态的容器
    • Generator:执行流程控制器
    • Async/Await:Generator+Promise的语法糖
  3. 选择建议
    • 现代项目首选Async/Await
    • 需要精细控制时使用Generator
    • 库开发考虑Promise兼容性

“任何足够复杂的技术方案都必然经历从分离到整合的演进过程” —— JavaScript异步编程发展印证了这一规律 “`

推荐阅读:
  1. Async/Await替代Promise的6个理由
  2. Generator函数与async函数的区别是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

javascript promise generator

上一篇:如何提升Win10开机速度

下一篇:Win10网络数据使用量一直为0怎么办

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》