前端异步任务处理总结

发布于:2025-08-04 ⋅ 阅读:(17) ⋅ 点赞:(0)

一、异步任务常见场景

  1. 网络请求fetch()axios 等 API 调用

  2. 定时操作setTimeoutsetInterval

  3. 用户交互:事件监听回调

  4. 资源加载:图片/脚本动态加载

  5. 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)

五、最佳实践

  1. 始终捕获错误:使用 try/catch 或 .catch()

  2. 避免嵌套地狱:优先使用 async/await 替代回调嵌套

  3. 合理使用并行:独立任务用 Promise.all() 或 Promise.allSettled()

  4. 添加取消机制:对长时间操作提供取消支持

  5. 性能优化

    • 请求合并(GraphQL/BFF)

    • 数据缓存(SWR/React Query)

    • 懒加载非关键资源


网站公告

今日签到

点亮在社区的每一天
去签到