你瞅啥呢

2026-05-22 多个异步任务如何“同步”执行?(deepseek)

要等待多个 fetchPromise 异步操作全部完成后,再执行下一个逻辑,可以使用 Promise.allPromise.allSettled

方法对比

方法 行为 适用场景
Promise.all() 全部成功才继续,有一个失败就立即停止 所有请求都必须成功,缺一不可
Promise.allSettled() 等全部完成(无论成功/失败),继续执行 能容忍部分请求失败,需要所有结果
Promise.race() 任意一个完成就继续 只需要最快的结果

1. 使用 Promise.all(全部成功才继续)

async function loadMultipleResources() {
  try {
    // 并发执行多个 fetch 请求
    const [usersRes, postsRes, commentsRes] = await Promise.all([
      fetch('/api/users'),
      fetch('/api/posts'),
      fetch('/api/comments')
    ]);

    // 所有请求成功后才能进入这里
    const users = await usersRes.json();
    const posts = await postsRes.json();
    const comments = await commentsRes.json();

    console.log('所有数据加载完成:', { users, posts, comments });
    
    // 在这里执行下一步逻辑
    await nextLogic(users, posts, comments);
    
  } catch (error) {
    // 任何一个请求失败,都会进入这里
    console.error('某个请求失败了:', error);
  }
}

function nextLogic(users, posts, comments) {
  console.log('执行后续逻辑...');
  // 处理数据、渲染页面等
}

2. 使用 Promise.allSettled(容忍部分失败)

async function loadMultipleResources() {
  // 并发执行,等待全部完成(无论成功或失败)
  const results = await Promise.allSettled([
    fetch('/api/users'),
    fetch('/api/posts'),
    fetch('/api/comments')
  ]);

  // 解析所有结果
  const data = {};
  
  results.forEach((result, index) => {
    if (result.status === 'fulfilled') {
      // 成功:处理数据
      const response = result.value;
      // 这里需要根据具体请求处理 response.json()
      console.log(`请求 ${index} 成功`);
    } else {
      // 失败:记录错误
      console.error(`请求 ${index} 失败:`, result.reason);
      data[`error_${index}`] = result.reason;
    }
  });

  // 无论部分请求是否失败,都会执行这里
  console.log('所有请求已完成(可能有失败的)');
  await nextLogic();
}

3. 混合场景:先并发获取数据,再处理

async function loadUserAndPosts(userId) {
  try {
    // 同时获取用户信息和帖子列表
    const [userRes, postsRes] = await Promise.all([
      fetch(`/api/users/${userId}`),
      fetch(`/api/users/${userId}/posts`)
    ]);

    const user = await userRes.json();
    const posts = await postsRes.json();

    console.log('用户信息:', user);
    console.log('帖子列表:', posts);

    // 等待所有帖子详情加载完(动态并发)
    const postDetailsPromises = posts.map(post => 
      fetch(`/api/posts/${post.id}`).then(res => res.json())
    );
    
    // 等待所有帖子详情加载完成
    const postDetails = await Promise.all(postDetailsPromises);
    
    console.log('所有帖子详情:', postDetails);
    
    // 最后执行渲染逻辑
    renderPage(user, posts, postDetails);
    
  } catch (error) {
    console.error('加载失败:', error);
  }
}

4. 使用 Promise.all + 数据处理

async function fetchAndProcess() {
  // 定义多个请求
  const requests = [
    fetch('/api/data1'),
    fetch('/api/data2'),
    fetch('/api/data3')
  ];

  try {
    // 等待所有请求完成
    const responses = await Promise.all(requests);
    
    // 并行解析 JSON(不需要等待彼此)
    const data = await Promise.all(
      responses.map(res => res.json())
    );
    
    console.log('所有数据解析完成:', data);
    
    // 执行后续逻辑
    processData(data);
    
  } catch (error) {
    console.error('请求或解析失败:', error);
  }
}

5. 实际场景:批量更新表格数据

// 你项目中的实际场景:批量更新多个记录的批次号
async function batchUpdateBatchNos(records) {
  // 构建所有更新请求
  const updatePromises = records.map(record => 
    fetch('/api/update-batch', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id: record.id, batchno: record.eo45_batchno })
    }).then(res => {
      if (!res.ok) throw new Error(`更新失败: ${record.id}`);
      return res.json();
    })
  );

  try {
    // 等待所有更新完成
    const results = await Promise.all(updatePromises);
    console.log('所有批次更新成功:', results);
    
    // 刷新表格
    await refreshTable();
    showMessage('批量更新完成');
    
  } catch (error) {
    console.error('批量更新失败:', error);
    showMessage('部分更新失败,请重试');
  }
}

6. 带重试机制的并发请求

async function fetchWithRetry(url, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const res = await fetch(url);
      if (res.ok) return res;
    } catch (error) {
      if (i === retries - 1) throw error;
      await new Promise(r => setTimeout(r, 1000 * (i + 1))); // 延迟重试
    }
  }
}

async function loadMultipleWithRetry(urls) {
  const results = await Promise.allSettled(
    urls.map(url => fetchWithRetry(url))
  );
  
  const successful = results.filter(r => r.status === 'fulfilled');
  const failed = results.filter(r => r.status === 'rejected');
  
  console.log(`成功: ${successful.length}, 失败: ${failed.length}`);
  
  return { successful, failed };
}

总结

你的需求 推荐方案
全部成功才继续,有一个失败就停止 Promise.all()
容忍部分失败,等待全部完成 Promise.allSettled()
需要逐次处理(有依赖关系) await 分别调用,或用 for...of 循环
大量并发请求(如 >10 个) 使用 p-limit 等库限制并发数

最常用的模式:

const [data1, data2, data3] = await Promise.all([
  fetch('/api/1').then(r => r.json()),
  fetch('/api/2').then(r => r.json()),
  fetch('/api/3').then(r => r.json())
]);
// 三个请求都完成后执行这里
posted @ 2026-05-22 09:28  叶乘风  阅读(14)  评论(0)    收藏  举报