前端并发请求控制,一次最多并发3个

screens 监控详情页面,可以添加任意多个图表,当加载页面时,一次可能同时加载100个图表,就至少请求100个接口,此时有些服务可能就会请求不成功而报错。

分析原因:一次请求过多接口时,服务器承受不住就会失败

解决方案:前端控制一次最多请求3个接口,再以此请求后面的接口

concurrent.js - 封装请求拦截

// fake request
const request = (url, callback) =>
  setTimeout(() => callback(`request "${url}" si finished`), 2000);
// function promisify
const toPromise = (url, req) => new Promise((resolve) => req(url, resolve));

// multiple requests
const concurrent = (urls, max) => {
  // transform the requests to a queue of runners
  const queue = urls.map((url) => () => toPromise(url, request));
  // slice to two queues
  const init = queue.slice(0, max);
  const rest = queue.slice(max);

  // construct a composer
  const executor = (runner, rest) =>
    runner().then((result) => {
      // handle request result
      console.log(result);
      // arrange those requests
      // the next request is initiated only if one request is completed,
      // so it can be judged that only a certain number of requests are in a concurrent state
      if (rest.length > 0) {
        const runner = rest.shift();
        executor(runner, rest);
      }
    });

  init.forEach((runner) => executor(runner, rest));
};

const urls = [
  "url 1",
  "url 2",
  "url 3",
  "url 4",
  "url 5",
  "url 6",
  "url 7",
  "url 8",
  "url 9"
];

concurrent(urls, 2);

页面中需要请求100个图表接口,控制最多并发3个请求

/**
 * 控制并发请求
 * 需求:页面中需要请求100个图表接口,控制最多并发3个请求
 */
const limitRequest = (max) => {
  const limit = max;
  const requests = [];
  let currentSum = 0;

  const run = async() => {
    try {
      ++currentSum;
      const fn = requests.shift();
      await fn();
    } catch (err) {
      console.log("Error", err);
    } finally {
      --currentSum;
      if (requests.length > 0) {
        run();
      }
    }
  }
  return (reqFn) => {
    if (!reqFn || !(reqFn instanceof Function)) {
      console.error("当前请求不是一个Function", reqFn);
      return;
    }
    requests.push(reqFn);
    if (currentSum < limit) {
      run();
    }
  }
}

let a = (msg) => () => new Promise((resolve) => {
  setTimeout(() => {
    resolve(msg);
  }, 1000);
}).then((data) => console.log(data));

let newRequest = limitRequest(3);
newRequest(a(1));
newRequest(a(2));
newRequest(a(3));
newRequest(a(4));
newRequest(a(5));
newRequest(a(6));
上次更新:
Contributors: jingmin.jiang