1️⃣ 什么是 Promise?
Promise 是 JavaScript 为了解决回调地狱(callback hell)问题而引入的一种异步编程解决方案。
const promise = new Promise((resolve, reject) => {
// 异步操作
if (success) {
resolve(result);
} else {
reject(error);
}
});
-
resolve(value):代表成功,状态变为 fulfilled。 -
reject(error):代表失败,状态变为 rejected。
Promise 有三种状态:
| 状态 | 含义 |
|---|---|
| pending | 等待中 |
| fulfilled | 已成功 |
| rejected | 已失败 |
2️⃣ Promise 的使用
基本链式调用
promise
.then((res) => console.log(res))
.catch((err) => console.error(err))
.finally(() => console.log('done'));
-
.then():接收成功回调。 -
.catch():接收失败回调。 -
.finally():无论成功失败都会执行。
3️⃣ Promise 的特性
-
一旦状态改变,就不可再次更改(不可逆)。
-
then/catch 注册的是微任务。
-
多次
.then()/.catch()不会导致 Promise 重复执行。
4️⃣ async / await 是什么?
-
async是用来声明一个异步函数,它会自动将返回值包装成Promise。 -
await是用来等待一个 Promise 执行完成。
async function getData() {
try {
const result = await fetch('/api/data');
console.log(result);
} catch (err) {
console.error(err);
}
}
等价形式:
fetch('/api/data')
.then((res) => console.log(res))
.catch((err) => console.error(err));
5️⃣ async/await 的底层原理
✅ 本质上是 Promise + 语法糖
async function foo() {
const res = await Promise.resolve('hello');
return res;
}
等价于:
function foo() {
return Promise.resolve('hello');
}
-
await会暂停当前函数的执行,等到 Promise 结果返回后再继续。 -
await后面可以跟普通值、Promise 或 async 函数。
6️⃣ await 的行为细节
-
如果
await后是普通值,会自动包装成 Promise。 -
如果是 Promise,会等待该 Promise resolve 后再继续执行。
-
await后的表达式执行异常,相当于Promise.reject(),需用try/catch捕获。
await 1; // 相当于 await Promise.resolve(1);
await Promise.reject('error'); // 抛出错误
7️⃣ async/await 和 Promise 的对比
| 特性 | Promise | async/await |
|---|---|---|
| 可读性 | 回调链可能较长 | 代码更清晰,类似同步流程 |
| 错误处理 | .catch() 捕获 | try...catch 捕获 |
| 并发处理 | .all(), .race() | 可用 Promise.all() 搭配 await |
| 使用难度 | 略高 | 较低,适合结构化异步代码 |
8️⃣ 并发 & 串行执行技巧
并发(同时执行多个异步任务):
await Promise.all([task1(), task2(), task3()]);
串行(一个一个顺序执行):
await task1();
await task2();
await task3();
9️⃣ 实现简易版 Promise(简化版)
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = null;
this.reason = null;
this.onResolved = [];
this.onRejected = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onResolved.forEach(fn => fn());
}
};
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejected.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
if (this.state === 'fulfilled') {
onFulfilled(this.value);
} else if (this.state === 'rejected') {
onRejected(this.reason);
} else {
this.onResolved.push(() => onFulfilled(this.value));
this.onRejected.push(() => onRejected(this.reason));
}
}
}
🔟 常见面试题分析
❓ Promise 为什么只执行一次?
const p = new Promise(resolve => {
console.log('start');
resolve();
});
p.then(() => console.log('then1'));
p.then(() => console.log('then2'));
✅ 输出:
start
then1
then2
解释:Promise 执行器立即执行,then 不会触发多次执行,而是订阅回调。
❓ async/await 为何只输出一次“开始”?
const a = new Promise(resolve =>
setTimeout(() => {
console.log('开始');
resolve('done');
}, 1000)
);
async function b() {
await a;
console.log('结束b');
}
function c() {
a.then(() => {
console.log('结束c');
});
}
b();
c();
✅ 输出:
开始
结束c
结束b
✅ 原因:a 是同一个 Promise,只执行一次定时器。多次 await 或 .then() 不会重复触发执行器。
❓ 为什么下述代码 await 不生效
const e = async () => {
await Promise.resolve(setTimeout(() => {
console.log('xx');
}, 1000))
console.log('xxxx');
}
setTimeout 本身 不是一个 Promise,它返回的是一个定时器 ID(数字),所以你 Promise.resolve(setTimeout(...)) 实际上是:
await Promise.resolve(42); // 假设返回的 timer id 是 42
正确写法
await new Promise((resolve) => {
setTimeout(() => {
console.log('xx');
resolve();
}, 1000);
});
✅ 总结
| 内容 | 总结 |
|---|---|
| Promise | 用于异步操作,状态不可逆 |
| async/await | 是基于 Promise 的语法糖,更符合同步编程习惯 |
| await 原理 | 会暂停当前函数的执行,等待 Promise resolve 结果 |
| 多次 then | 不会重复执行 Promise,都会接收相同的结果 |
| 异常处理 | Promise 用 .catch(),async/await 用 try/catch |
| 并发处理 | 使用 Promise.all 进行并发 |