JavaScript 异步编程总结:Promise、Generator 及 async/await

1. Promise

定义:一种异步编程代码组织方案,在 JavaScript 中是一个对象,用于处理异步操作;它代表了一个最终可能 resolved(或 rejected)及其结果值的操作。

实现原理:状态机+链式调用+观察者模式

  • 状态机:有三种状态 pending、resolved、reject,一旦状态改变,就不能再次改变。
  • 链式调用 :thenable,.then.catch会返回一个新的 Promise 对象(值为 then 中的返回值),可用于链式调。
  • 观察者模式:then 中订阅,resolve 中通知。

解决问题:callback hell -> 可读性提高。

示例

Callback 模式:

js 复制代码
getData(function(error, a){
    if (error) {
        // Handle error
    } else {
        getMoreData(a, function(error, b){
            if (error) {
                // Handle error
            } else {
                getMoreData(b, function(error, c){ 
                    if (error) {
                        // Handle error
                    } else {
                        getMoreData(c, function(error, d){ 
                            if (error) {
                                // Handle error
                            } else {
                                // Do something with 'd'
                            }
                        });
                    }
                });
            }
        });
    }
});

Promise 模式:

js 复制代码
getData()
.then(a => getMoreData(a))
.then(b => getMoreData(b))
.then(c => getMoreData(c))
.then(d => {
    // Do something with 'd'
})
.catch(e => {
    // Handle any error that occurred along the way
});

promisesaplus.com/

2. Generator

定义:Generator 是 ES6 引入的一种特殊函数类型,在 JavaScript 中,它可以在执行过程中暂停,并在稍后再恢复执行,可多次执行。

实现原理

  • 迭代器模式 :Generator 函数返回一个特殊的迭代器,这个迭代器封装了函数体内部的操作。每次调用迭代器的 next 方法,就会执行到函数体中的下一个 yield 表达式,然后暂停。
  • 暂停与恢复执行 :使用 yield 关键字可以暂停函数的执行,并将控制权返回给调用者。当再次调用迭代器的 next 方法时,函数会从暂停的地方恢复执行,直到遇到下一个 yield 表达式或到达函数末尾。

解决问题:代码执行时机可控制,可惰性执行。

示例

在内存中生成了整个斐波那契数列,然后进行迭代:

js 复制代码
function fibonacci(n) {
  const sequence = [0, 1];
  for (let i = 2; i < n; i++) {
    sequence[i] = sequence[i - 1] + sequence[i - 2];
  }
  return sequence;
}

console.log(fibonacci(1000)); // 输出前 1000 个斐波那契数

每次迭代时只生成一个值,而不是一次生成整个数列:

js 复制代码
function* fibonacci() {
  let [prev, curr] = [0, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

// 创建一个斐波那契数列的 generator
const sequence = fibonacci();

// 输出前 1000 个斐波那契数
for (let i = 0; i < 1000; i++) {
  console.log(sequence.next().value);
}

3. async/await

定义async/await 是 ES2017 引入的一种新的处理异步操作的方式,提供了一种更直观,更简洁的方式来组织异步代码。(实质上是 Generator 和 Promise 的语法糖,but better)

The behavior of async/await is similar to combining generators and promises。

实现原理

  • 异步函数 :通过 async 关键字声明的函数,函数返回一个 Promise。
  • 暂停执行await 关键字可以暂停 async 函数的执行,等待 Promise 被 resolved,然后恢复执行,并返回 resolved 的值。

解决问题:代码组织和错误处理更直观。

示例

Promise 模式:

js 复制代码
getData()
.then(a => getMoreData(a))
.then(b => getMoreData(b))
.then(c => getMoreData(c))
.then(d => {
    // Do something with 'd'
})
.catch(e => {
    // Handle any error that occurred along the way
});

async/await模式:

js 复制代码
async function fetchDataAsync() {
  try {
    const a = await getData();
    const b = await getMoreData(a);
    const c = await getMoreData(b);
    const d = await getMoreData(c);
    // Do something with 'd'
  } catch (error) {
    // Handle error
  }
}

fetchDataAsync();
相关推荐
kyriewen6 小时前
AI 写的 React 组件,合并前必查的 6 个坏味道——每个都有代码对比
前端·javascript·react.js
多加点辣也没关系7 小时前
JavaScript|第13章:原始类型的方法
开发语言·javascript·ecmascript
এ慕ོ冬℘゜7 小时前
深入理解 JavaScript 事件体系:Window、鼠标与键盘事件详解
开发语言·javascript·okhttp
摇滚侠8 小时前
SpringBoot3+Vue3 全套视频教程 45-51
前端·javascript·vue.js
触底反弹9 小时前
🔥 RAG 到底是怎么工作的?掰开揉碎了给你讲明白!
javascript·人工智能·后端
Hilaku9 小时前
前端大裁员背后的恐慌:我们还剩什么底牌?
前端·javascript·程序员
云空9 小时前
《Three.js 3D实例大全》
开发语言·javascript·3d·three.js
云空10 小时前
《Three.js 3D坦克对战【AI单机版】》
javascript·人工智能·3d·three.js
默_笙10 小时前
🚲 手写一个"Claude Code":我用 LangChain + ReAct 循环,让 AI 自己读文件、解释代码
前端·javascript
等咸鱼的狸猫11 小时前
# JS 核心六大主题:闭包内存模型、原型链查找、事件流机制与 Promise / Event Loop 实现视角复盘
前端·javascript