彻底讲通 JavaScript 的 Promise
本文由一缘原创整理,内容涵盖 Promise 的本质、常见用法、链式调用、错误处理、并发控制、常见陷阱与最佳实践,配合丰富代码和输出,适合所有前端开发者。
彻底讲通 JavaScript 的 Promise
Promise 是现代 JavaScript 异步编程的基石。理解 Promise,不仅能写出更优雅的异步代码,还能为 async/await 打下坚实基础。
1. Promise 是什么?
Promise 是一个代表未来某个异步操作结果的对象,有三种状态:
- pending(进行中)
- fulfilled(已成功)
- rejected(已失败)
一旦状态变为 fulfilled 或 rejected,就不可再变。
2. Promise 的基本用法
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功!');
}, 1000);
});
p.then(result => {
console.log(result);
});
输出:
(1秒后) 成功!
3. Promise 的链式调用
then() 返回的也是一个 Promise,可以链式调用:
Promise.resolve(1)
.then(x => x + 1)
.then(x => x * 2)
.then(x => {
console.log(x);
return x;
});
输出:
4
4. 捕获异常与 catch
Promise.reject('出错了')
.then(res => {
// 不会执行
})
.catch(err => {
console.log('捕获到错误:', err);
});
输出:
捕获到错误: 出错了
5. finally 的用法
finally 无论 Promise 成功还是失败都会执行:
Promise.resolve('ok')
.finally(() => {
console.log('无论如何都会执行');
})
.then(res => console.log(res));
输出:
无论如何都会执行
ok
6. Promise.all 与 Promise.race
Promise.all
所有 Promise 都成功才 resolve,有一个失败就 reject:
Promise.all([
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
]).then(res => console.log(res));
输出:
[1, 2, 3]
Promise.race
谁先完成就返回谁的结果:
Promise.race([
new Promise(res => setTimeout(() => res('A'), 100)),
new Promise(res => setTimeout(() => res('B'), 50))
]).then(res => console.log(res));
输出:
B
7. Promise.allSettled 与 Promise.any
Promise.allSettled
无论成功失败,全部执行完后返回每个 Promise 的结果状态:
Promise.allSettled([
Promise.resolve('ok'),
Promise.reject('fail')
]).then(res => console.log(res));
输出:
[
{ status: 'fulfilled', value: 'ok' },
{ status: 'rejected', reason: 'fail' }
]
Promise.any
只要有一个成功就 resolve,全失败才 reject:
Promise.any([
Promise.reject('fail'),
Promise.resolve('ok')
]).then(res => console.log(res));
输出:
ok
8. Promise 的常见陷阱
then/catch 没有返回新 Promise
Promise.resolve(1)
.then(x => {
// 忘记 return
x + 1;
})
.then(x => console.log(x));
输出:
undefined
then/catch 里抛出异常
Promise.resolve()
.then(() => {
throw new Error('出错了');
})
.catch(e => console.log(e.message));
输出:
出错了
9. Promise 的最佳实践
- 总是返回 Promise,不要混用回调和 Promise。
- 链式调用时记得 return,否则下一个 then 得到 undefined。
- 错误要 catch,否则会被吞掉。
- 避免 Promise 嵌套,用链式写法更优雅。
- async/await 是 Promise 的语法糖,理解 Promise 是写好 async/await 的基础。
10. 手写一个最简 Promise
理解原理,手写一个极简 Promise:
class MyPromise {
constructor(fn) {
this.cbs = [];
fn(this.resolve.bind(this));
}
resolve(val) {
setTimeout(() => {
this.cbs.forEach(cb => cb(val));
});
}
then(cb) {
this.cbs.push(cb);
return this;
}
}
new MyPromise(res => res(42)).then(x => console.log(x));
输出:
42
11. async/await 与 Promise
async 函数返回的就是 Promise,可以用 await 等待 Promise 结果:
function delay(ms) {
return new Promise(res => setTimeout(res, ms));
}
async function main() {
await delay(100);
console.log('done');
}
main();
输出:
done
结语
Promise 是 JS 异步的核心,理解它能让你写出更健壮、优雅的前端代码。欢迎留言交流更多 Promise 相关问题!