JS—Promise:3分钟掌握Promise
个人博客:haichenyi.com。感谢关注
一. 目录
- 一–目录
- 二–Promise 的三种状态
- 三–创建 Promise
- 四–Promise 的实例方法
- 五–链式调用(Chaining)
- 六–静态方法
- 七–常见使用场景
- 八–错误处理最佳实践
- 九–Promise 的局限性
- 十–进阶:Async/Await
二. Promise 的三种状态
JavaScript ES6新增的Promise是用于处理异步编程的对象,它解决了传统回调地狱的问题。使异步代码更加简洁,易读懂,易维护。
- Pending(进行中): 初始状态,既未完成也为拒绝
- Fulfilled(已成功): 异步操作成功,通过resolve()触发修改
- Rejected(已失败): 异步操作失败,通过reject()触发修改
状态转换规则
- 不可逆,一旦转换为Fulfiled或者Rejected就不能再修改(只能从Pending—>Fulfilled,Pending—>Rejected)。
- 未处理的Rejected,Promise会导致控制台会报错(Uncaught Promise Rejection)
三. 创建 Promise
通过new Promise() 构造方法创建一个promise对象,需要传递一个执行器函数(executor) ,它需要接收两个回调函数,一个成功回调resolve ,一个失败回调reject
let p = new Promise((resolve, reject) => {
//异步操作ajax,定时器等等
setTimeout(() => {
let success = Math.random() > 0.5;
success ? resolve("操作成功!") : reject("操作失败!");
}, 1000);
})
四. Promise 的实例方法
4.1. .then()
添加状态改变时的回调函数,接收两个回调参数
- onFulfilled():成功时的回调
- onRejected():失败时的回调(可选,一般都是用catch)
promise.then(
(value) => console.log(value), // 成功时执行
(error) => console.error(error) // 失败时执行(可选)
);
4.2. .catch()
捕获Promise链式调用中的错误(相当于 .then(null, onRejected))
promise
.then((value) => console.log(value))
.catch((error) => console.error(error)); // 统一处理错误
4.3. .finally()
无论成功或者失败都会执行,常用于清理操作
promise
.then((value) => console.log(value))
.catch((error) => console.error(error))
.finally(() => console.log("操作完成"));
五. 链式调用(Chaining)
每个.then()或.catch返回一个新的promise,支持链式调用
fetchData()
.then((data) => processData(data)) // 返回新 Promise
.then((result) => saveResult(result))
.catch((error) => handleError(error));
链式调用的规则:
- 如果函数返回非promise的值(如数字,字符串等等),会自动包装成Promise.resolve(value)
- 如果函数返回另一个promise,则等待其状态改变后再触发后续流程
六. 静态方法
6.1 Promise.resolve(value)
创建一个成功的promise
Promise.resolve(42).then((value) => console.log(value)); // 42
6.2 Promise.reject(error)
创建一个失败的promise
Promise.reject("出错啦").catch((error) => console.error(error));
6.3 Promise.all(iterable)
等待所有的promise成功,或者其中一个失败
const promises = [fetchData1(), fetchData2(), fetchData3()];
Promise.all(promises)
.then((results) => console.log("全部成功:", results))
.catch((error) => console.error("至少一个失败:", error));
所有的promise都成功,则走成功回调。
只要其中一个失败,则立马走失败回调
6.4 Promise.race(iterable)
取第一个改变状态的promise的值,可以是成功,也可以是失败
Promise.race([fetchData(), timeout(5000)])
.then((result) => console.log("先完成的任务:", result));
6.5 Promise.allSettled(iterable)
等待所有的promise都执行完成,不论是成功还是失败,都要等待所有的都执行完
Promise.allSettled(promises)
.then((results) => results.forEach((result) => console.log(result.status)));
七. 常见使用场景
7.1 替代回调函数
将回调风格的 API 转换为 Promise:
function readFilePromise(path) {
return new Promise((resolve, reject) => {
fs.readFile(path, (err, data) => {
err ? reject(err) : resolve(data);
});
});
}
7.2 并发请求
使用 Promise.all 并行处理多个异步操作。
7.3 异步流程控制
链式调用实现顺序执行多个异步任务。
八. 错误处理最佳实践
- 始终添加 .catch(): 避免未处理的 Promise 错误。
- 在链式末尾统一处理错误: 使用单个 .catch() 捕获整个链中的错误。
- 区分操作错误与异常: 通过 reject 传递预期的业务错误,throw 抛出程序异常。
九. Promise 的局限性
- 无法取消: 一旦创建,必须等待其完成或失败。
- 错误需显式处理: 未捕获的 reject 会导致静默失败。
- 兼容性: 旧版浏览器需 polyfill(如 ES6-Promise)。
十. 进阶:Async/Await
async/await 是基于 Promise 的语法糖,让异步代码更像同步代码:
async function fetchData() {
try {
const data1 = await simulateAsyncTask(1000);
const data2 = await simulateAsyncTask(500);
console.log(data1, data2);
} catch (error) {
console.error(error);
}
}
掌握 Promise 是理解现代 JavaScript 异步编程的关键,结合 async/await 可以写出更简洁、健壮的代码。