一、异步任务常见场景
网络请求:
fetch()
、axios
等 API 调用定时操作:
setTimeout
、setInterval
用户交互:事件监听回调
资源加载:图片/脚本动态加载
Web Workers:后台线程计算
二、核心处理方案
1. Promise(ES6+)
function fetchUser(id) {
return new Promise((resolve, reject) => {
fetch(`/api/users/${id}`)
.then(response => response.json())
.then(resolve)
.catch(reject)
})
}
// 使用示例
fetchUser(123)
.then(user => console.log(user))
.catch(error => console.error(error))
2. async/await(ES2017+)
async function getUserData() {
try {
const user = await fetchUser(123)
const posts = await fetchPosts(user.id)
return { user, posts }
} catch (error) {
console.error('数据获取失败:', error)
return null
}
}
// 调用
getUserData().then(console.log)
3. Promise 组合方法
方法 | 特点 | 使用场景 |
---|---|---|
Promise.all() |
全部成功才返回,短路失败 | 强依赖的并行请求 |
Promise.allSettled() |
等待所有完成,返回状态详情 | 独立任务的结果收集 |
Promise.race() |
返回第一个完成的结果 | 请求超时控制 |
Promise.any() |
返回第一个成功的结果 | 多源数据择优 |
Promise.allSettled() 示例:
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 1');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 2');
}, 2000);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 3');
}, 3000);
});
Promise.allSettled([promise1, promise2, promise3])
.then(results => {
results.forEach(result => {
if(result.status === 'fulfilled') {
console.log('成功获取值:', result.value);
} else {
console.error('拒绝原因:', result.reason);
}
});
});
三、高级处理模式
1. 请求竞速(race)
function withTimeout(promise, timeout) {
return Promise.race([
promise,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('请求超时')), timeout)
)
])
}
// 使用
withTimeout(fetch('/api/data'), 5000)
.catch(error => console.error(error))
2. 顺序执行 + 并行组合
async function processOrder(orderId) {
// 顺序执行
const order = await fetchOrder(orderId)
const user = await fetchUser(order.userId)
// 并行执行
const [product, address] = await Promise.all([
fetchProduct(order.productId),
fetchAddress(user.addressId)
])
return { order, user, product, address }
}
3. 错误重试机制
async function retry(fn, retries = 3, delay = 1000) {
try {
return await fn()
} catch (err) {
if (retries <= 0) throw err
await new Promise(res => setTimeout(res, delay))
return retry(fn, retries - 1, delay * 2) // 指数退避
}
}
// 使用
retry(() => fetch('/unstable-api'))
四、实际应用技巧
加载状态管理:
async function loadData() {
setLoading(true)
try {
const data = await fetchData()
setState(data)
} catch (error) {
setError(error.message)
} finally {
setLoading(false)
}
}
并发控制(避免同时发起过多请求):
async function parallelWithLimit(tasks, limit) {
const results = []
const executing = []
for (const task of tasks) {
const p = task().then(res => {
executing.splice(executing.indexOf(p), 1)
return res
})
results.push(p)
executing.push(p)
if (executing.length >= limit) {
await Promise.race(executing)
}
}
return Promise.all(results)
}
// 使用:最多同时3个请求
parallelWithLimit([task1, task2, ...task10], 3)
五、最佳实践
始终捕获错误:使用
try/catch
或.catch()
避免嵌套地狱:优先使用 async/await 替代回调嵌套
合理使用并行:独立任务用
Promise.all()
或Promise.allSettled()
添加取消机制:对长时间操作提供取消支持
性能优化:
请求合并(GraphQL/BFF)
数据缓存(SWR/React Query)
懒加载非关键资源