Skip to content

如何用Promise.all实现并发请求?如何处理部分请求失败?

参考答案:

1. 用 Promise.all 实现并发请求

Promise.all 的特性是:等待所有 Promise 全部成功,才会进入 .then;如果有一个失败,会立刻进入 .catch

例子:

js
function fetchData(url) {
  return fetch(url).then(res => res.json());
}

Promise.all([
  fetchData('/api/user'),
  fetchData('/api/order'),
  fetchData('/api/message'),
]).then(([user, order, message]) => {
  console.log('全部成功:', user, order, message);
}).catch(error => {
  console.error('有请求失败:', error);
});

这样就能同时发起多个请求(并发),等结果全部回来再统一处理。


2. 如何处理 部分请求失败

方案 A: Promise.allSettled(推荐)

  • 它不会短路,所有 Promise 都会执行完。
  • 返回结果包含 status: "fulfilled""rejected"
js
Promise.allSettled([
  fetchData('/api/user'),
  fetchData('/api/order'),
  fetchData('/api/message'),
]).then(results => {
  results.forEach(result => {
    if (result.status === 'fulfilled') {
      console.log('成功:', result.value);
    } else {
      console.error('失败:', result.reason);
    }
  });
});

这样就能做到“部分成功也能拿到”。


方案 B: 手动封装 catch,让 Promise.all 不被短路

给每个请求加上 .catch,保证它不会抛错,而是返回一个标记:

js
function safeFetch(promise) {
  return promise
    .then(res => ({ status: 'fulfilled', value: res }))
    .catch(err => ({ status: 'rejected', reason: err }));
}

Promise.all([
  safeFetch(fetchData('/api/user')),
  safeFetch(fetchData('/api/order')),
  safeFetch(fetchData('/api/message')),
]).then(results => {
  console.log(results);
});

输出结构和 allSettled 一样,但可以兼容旧浏览器(没有 allSettled 的情况)。


方案 C: 按需兜底(部分失败时用默认值)

比如请求失败时,给个默认数据继续用:

js
Promise.all([
  fetchData('/api/user').catch(() => ({ name: '游客' })),
  fetchData('/api/order').catch(() => []),
  fetchData('/api/message').catch(() => []),
]).then(([user, order, message]) => {
  console.log('即使失败也有默认值:', user, order, message);
});

题目要点:

  • 只要全部成功才继续 → 用 Promise.all
  • 要拿到每个请求的完整结果(成功 + 失败) → 用 Promise.allSettled
  • 需要容错或兜底值 → 在每个 Promise 上加 catch