Promise与async await
JavaScript Promise 与 async/await 核心知识点总结
1. Promise 核心概念详解
1.1 三种状态 (Three States)
pending
: 初始状态fulfilled
: 成功状态rejected
: 失败状态- 特性: 状态一旦从
pending
变为fulfilled
或pending
变为rejected
,就不会再改变。
1.2 一个执行器函数 (Executor Function)
- 当
new Promise((resolve, reject) => { ... })
时,执行器函数executor(resolve, reject)
会立即同步执行。 resolve
和reject
是 JavaScript 引擎提供的两个函数,用于改变 Promise 的状态。
1.3 resolve
与 reject
回调
resolve(value)
: 将 Promise 状态从pending
改为fulfilled
,并将成功的结果value
传递出去。reject(reason)
: 将 Promise 状态从pending
改为rejected
,并将失败的原因reason
传递出去。- 重要特性:
- Promise 的状态一旦改变,就不能再变。
- 如果
resolve
和reject
都被调用(例如,在executor
函数内部),则以第一次调用为准,后续的调用将被忽略。
1.4 实例方法 (Instance Methods)
then(onFulfilled, onRejected)
:onFulfilled
: (可选) Promise 状态变为fulfilled
时执行的回调。onRejected
: (可选) Promise 状态变为rejected
时执行的回调。- 返回一个新的 Promise,可以实现链式调用。
catch(onRejected)
:- 相当于
then(null, onRejected)
或then(undefined, onRejected)
,用于捕获rejected
状态。 - 返回一个新的 Promise。
- 相当于
finally(onFinally)
:- 无论 Promise 最终状态是
fulfilled
还是rejected
,onFinally
回调都会执行。 - 返回一个新的 Promise。
- 无论 Promise 最终状态是
2. executor
同步执行与 Promise 的初始状态
- 当
new Promise(executor)
时,executor(resolve, reject)
函数会立即同步执行。 - 在
executor
函数内部的resolve
或reject
被调用之前,Promise 的初始状态是pending
。 - Promise 最终会变成
fulfilled
还是rejected
,取决于在executor
函数内部是调用了resolve(value)
还是reject(reason)
。 - 如果
executor
函数执行完毕,但既没有调用resolve
也没有调用reject
(例如,它们在一个尚未完成的异步操作中),则 Promise 会一直保持pending
状态。
3. Promise 与 async/await
的区别与联系
特性 (Feature) | Promise | async/await |
---|---|---|
核心概念 | 表示一个异步操作最终完成或失败及其结果值的对象。 | 基于 Promise 构建的语法糖,旨在以更同步的方式编写异步代码。 |
语法形式 | 使用 .then() , .catch() , .finally() 链式调用。 |
async 用于声明异步函数 (隐式返回 Promise);await 用于等待 Promise。 |
代码可读性 | 多个 .then() 嵌套时,可读性可能下降。 |
代码结构更接近同步代码,通常更简洁、易于理解和维护。 |
错误处理 | 主要通过 .catch() 方法或 .then() 的第二个参数。 |
可以使用标准的 try...catch 结构,更符合同步代码习惯。 |
返回值 | .then() 等方法返回新的 Promise。 |
async 函数总是隐式返回一个 Promise。 |
本质关系 | Promise 是异步编程的基础和核心。 | async/await 是建立在 Promise 之上的更高阶抽象。 |
面试核心回答建议:
Promise 是异步编程的基石和核心对象。而 async/await
是建立在 Promise 之上的、旨在简化异步代码写法和提升可读性的语法特性,它让我们能以更像同步代码的方式来组织异步逻辑,并且提供了更自然的错误处理机制,其核心依然是 Promise。
4. async/await
如何实现“链式调用”效果
async/await
本身不使用像 Promise 那样的 .then().then()
显式链式方法,但它通过更直观的方式实现了异步操作的顺序执行和数据传递(即 Promise 链式调用的核心目的):
-
顺序
await
实现串行执行:- 在一个
async
函数内部,可以按顺序await
多个返回 Promise 的异步操作。 - 每一行
await
都会暂停当前async
函数的执行,直到它所等待的 Promise 完成,然后才会继续执行下一行代码,自然形成操作的“链条”。
- 在一个
-
数据通过变量传递:
await
表达式会返回 Promise 解析后的值。- 可以直接将此值赋给变量,在后续的
await
操作或同步逻辑中使用,比在.then()
回调中层层传递参数更简洁。
效果对比示例:
-
Promise 的
.then()
链:// function asyncOperation1() { /* ... */ } // function asyncOperation2(data) { /* ... */ } // function asyncOperation3(data) { /* ... */ } // asyncOperation1() // .then(result1 => { // return asyncOperation2(result1); // }) // .then(result2 => { // return asyncOperation3(result2); // }) // .then(finalResult => { // console.log("最终结果:", finalResult); // }) // .catch(error => { // console.error("错误:", error); // });
-
async/await
实现等效逻辑:// async function asyncOperation1() { /* ... */ } // async function asyncOperation2(data) { /* ... */ } // async function asyncOperation3(data) { /* ... */ } // async function fetchDataChain() { // try { // const result1 = await asyncOperation1(); // const result2 = await asyncOperation2(result1); // const finalResult = await asyncOperation3(result2); // console.log("最终结果:", finalResult); // } catch (error) { // console.error("错误:", error); // } // } // fetchDataChain();
async/await
通过其同步化的代码结构,天然支持了异步任务的串行化,使得代码逻辑更清晰。