问题描述

创建一个请求控件器,支持连续发起请求,如果超过请求限制则需要等其他请求返回之后再发送后续请求

function createFetch(limit: number) {
  // todo
}
const myFetch = createFetch(3);

myFetch('/api/1').then(res => {
  console.log('api-1');
}).catch(err => {})
myFetch('/api/2').then(res => {
  console.log('api-2');
}).catch(err => {})
myFetch('/api/3').then(res => {
  console.log('api-3');
}).catch(err => {})
// 需要等待上述请求返回
myFetch('/api/4').then(res => {
  console.log('api-4');
}).catch(err => {})

思路解析

有两点注意点:

  1. 并发的控制,一般情况就是通过一个变量来判断是否超过限制,如果超过就需要等之前的请求完成之后再次发送请求;
  2. 每一个请求需要返回一个promise,以支持链式调用;

代码实现

function createFetch(limit) {
  // [url, resolve, reject];
  const queue = [];

  // 当前请求的个数
  let count = 0;

  const request = () => {
    // 判断一下queue,每次一个请求完成后,都会再次执行request
    if (count < limit && queue.length) {
      const [url, resolve, reject] = queue.shift();
      // 实际运行是可以使用setTimeout模拟一下fetch
      // finally默认返回then/catch的结果
      fetch(url).finally(() => {
        count--;
        request();
      }).then(resolve, reject);
      // 执行一次,添加一次
      count++;
    }
  }

  return (url) => new Promise((resolve, reject) => {
    queue.push([url, resolve, reject]);
    request();
  })
} 

一个扩展写法为:合并 100ms 内发送的请求

Last Updated:
Contributors: tiodot