ES11 中的 Promise.all 方法并发请求的最佳实践

随着互联网的发展,现代化的 Web 应用越来越依赖于网络数据传输和接口调用。在前端开发中,经常会遇到需要发起多个并发请求获取数据的情况。而 ES11 中新增的 Promise.all() 方法可以非常方便地实现并发请求,并且在处理多个异步操作时具有重要的实践意义。

Promise.all() 方法的使用

Promise.all() 方法接受一个 Promise 对象数组作为参数,返回一个新的 Promise 数组,该数组包含原始数组中每个 Promise 对象的解析值。在所有 Promise 对象都成功解析时,返回的 Promise 对象才会解析成功。

下面是一段示例代码,展示如何使用 Promise.all() 方法实现并发请求:

const urls = [
  'https://api.example.com/user/1',
  'https://api.example.com/user/2',
  'https://api.example.com/user/3'
];

const promises = urls.map(url => fetch(url));

Promise.all(promises).then(responses => {
  // 处理所有请求返回的响应
  ...
}).catch(error => {
  // 处理任何一个请求失败的情况
  ...
});

上述代码中,我们定义了一个 urls 数组存储需要请求的接口地址,然后通过 map() 方法将每个地址转化成一个 Promise 对象保存到 promises 数组中。最后调用 Promise.all() 方法并将 promises 数组作为参数,该方法返回一个新的 Promise 对象,当所有 Promise 对象都成功解析时,返回的 Promise 对象才会解析成功。我们可以在 then() 方法中处理所有请求返回的响应数据,也可以在 catch() 方法中处理任何一个请求失败的情况。

避免请求阻塞并控制并发数量

在实际开发中,我们需要考虑请求的性能优化和控制并发请求的数量。特别是在请求对象较多或请求较慢的情况下,如果同时发起多个请求,可能会导致页面性能下降和用户体验下降。在这种情况下,使用 Promise.all() 方法需要注意以下几点:

  • 尽量使用请求优化的方法,减少响应时间和大小,例如使用 gzip 压缩、缓存控制、请求划分等方法;
  • 为了避免请求阻塞,我们可以将部分接口通过 setTimeout 或 setImmediate 在一定时间后发起,而不是立即发起所有请求;
  • 为了控制并发请求的数量,我们可以通过 Promise 的 race() 方法,监控正在运行的 Promise 对象,当有一个 Promise 对象解析完成时,立即发起另外一个 Promise 对象的请求,从而有效控制并发数量。

下面是一段基本代码,实现了通过 setTimeout 限制并发数量的示例:

const urls = [
  'https://api.example.com/user/1',
  'https://api.example.com/user/2',
  'https://api.example.com/user/3',
  'https://api.example.com/user/4',
  'https://api.example.com/user/5'
];

const concurrentNumber = 2; // 控制并发数量为 2

let currentIndex = 0;

function getRequest(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      fetch(url).then(response => {
        resolve(response);
      }).catch(error => {
        reject(error);
      });
    }, 1000);
  });
}

function request() {
  const promises = [];
  for (let i = 0; i < concurrentNumber && currentIndex < urls.length; i++) {
    promises.push(getRequest(urls[currentIndex]));
    currentIndex++;
  }
  Promise.all(promises).then(responses => {
    // 处理所有请求返回的响应
    ...
    if (currentIndex < urls.length) {
      request();
    }
  }).catch(error => {
    // 处理任何一个请求失败的情况
    ...
    if (currentIndex < urls.length) {
      request();
    }
  });
}

request();

上述代码中,我们通过将并发数量控制为 2,并在 getRequest() 方法中使用 setTimeout 限制请求的发起时间,有效避免过多并发请求导致阻塞和性能下降的问题。

总结

Promise.all() 方法是 ES11 中重要的异步操作工具,可以非常方便地实现并发请求,并控制请求的数量和优化请求的性能。在实践中,我们需要注意避免请求阻塞和控制并发数量,以保证应用的性能和用户体验。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a25b34add4f0e0ffa7c596


纠错反馈