前端异步任务处理总结
一、异步任务常见场景
网络请求:
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 errawait 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)
懒加载非关键资源