异步 Promise
shell
# Promise
ES6 引入的解决方案,代表一个异步操作的最终完成或失败
Promise 本身是个构造函数,接受一个回调函数作为参数,回调函数有两个参数,分别是 resolve reject ,二者都是方法,执行时传入最终成功或者失败的结果
# 优缺点
优点:链式调用解决了回调地狱问题,更好的错误处理(catch),更多的并发处理方法(Promise.all, Promise.race)
缺点:仍然需要回调(then/catch)
# 特点
状态一旦改变,不可逆
只能 pending → fulfilled 或 pending → rejectedPromise 的所有方法
shell
# 实例方法
.then()
.catch()
.finally()
# 静态方法
Promise.resolve(value) 直接返回正确状态的 Promise 对象
Promise.reject(reason) 直接返回错误状态的 Promise 对象
Promise.all([p1,p2,p3]) "全成则成,一败则败" 入参为**可迭代的 Promise 列表**;全部成功则成功、任一失败则失败、返回与入参顺序一致的结果数组或第一个 rejection
Promise.allSettled([p1,p2,p3]) "等待所有,无论成败" 全部 settled 后返回状态数组(fulfilled/rejected 各自带 value/reason)
Promise.race([p1,p2,p3]) "竞速" 以**最先 settled** 的为准,成功则 fulfilled、失败则 rejected
Promise.any([p1,p2,p3]) "任一成功即成功" 任一 fulfilled 即成功;全部 rejected 才失败(ES2021,需运行环境支持)使用案例
异步封装
- 在函数中返回 Promise 对象
- 在 Promise 构造函数的回调参数中执行异步操作
- 操作函数的 .then .catch 方法实现异步操作
js
function request() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const ok = Math.random() > 0.5;
ok ? resolve('成功') : reject('失败');
}, 500);
});
}
request()
.then((res) => console.log(res))
.catch((err) => console.log(err));并发 - 超时控制
js
function fetchWithTimeout(fetchPromise, timeout = 5000) {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject('timeout'), timeout)
})
return Promise.race([fetchPromise, timeoutPromise])
}并发 - 失败重试机制
js
async function retry(fn, maxTimes = 3) {
try {
return await fn()
} catch (err) {
if (maxTimes > 0) {
return retry(fn, maxTimes - 1)
}
throw err
}
}并发 - 限制同时进行的最大请求数
同时最多执行 limit 个异步任务
js
async function concurrentLimit(tasks, limit = 2) {
const result = []
const executing = []
for (const task of tasks) {
const p = Promise.resolve(task()).then(res => result.push(res))
executing.push(p)
if (executing.length >= limit) {
await Promise.race(executing)
}
}
await Promise.all(executing)
return result
}接口并发请求(真实项目常用)
js
async function getData() {
try {
const [userList, orderList, goodsList] = await Promise.all([
fetch('/api/userList').then(res => res.json()),
fetch('/api/orderList').then(res => res.json()),
fetch('/api/goodsList').then(res => res.json())
]);
console.log('用户', userList);
console.log('订单', orderList);
console.log('商品', goodsList);
} catch (err) {
console.log('任意一个接口失败,整体失败', err);
}
}Promise.then() 方法的使用案例
js
// 红灯三秒、绿灯两秒、黄灯一秒,循环往复
function red() {
console.log('red');
}
function green() {
console.log('green');
}
function yellow() {
console.log('yellow');
}
function light(timer,cb) {
return new Promise((resolve, reject) => {
setTimeout(() => {
cb()
resolve()
}, timer);
})
}
function step() {
Promise.resolve()
.then(() => light(3000,red))
.then(() => light(2000,green))
.then(() => light(1000,yellow))
.then(() => step())
}
// async await 方案
async function step() {
await light(3000, red); // 等3秒 → 亮红灯
await light(2000, green); // 等2秒 → 亮绿灯
await light(1000, yellow); // 等1秒 → 亮黄灯
step(); // 循环
}
step()JS 异步 Promise(另一稿)
解释一下 Promise 的原理和用法?
shell
# 用法
Promise 是一种异步操作的解决方案,用于处理异步操作的结果或错误。
# 原理
Promise 有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。状态一旦改变就不能再变。Promise 实例化时传入执行器函数,执行器函数立即执行,成功时调用 resolve,失败时调用 reject。
还可通过 Promise.all、Promise.race 等方法处理多个 Promise。