javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > 前端请求并发和请求覆盖

前端请求并发和请求覆盖的解决方法

作者:Cder

最近在开发一些大屏,涉及到比较多的数据来源,接口也没有做聚合,导致页面需要调很多接口来填充页面数据,那么就会有接口并发的问题出现,所以本文给大家介绍了如何解决前端请求并发和请求覆盖,需要的朋友可以参考下

页面太多接口并发请求会出现什么问题?

解决方式也有很多,比如:

以上都是基于运维和后端的角度,那么前端如何解决呢?

并发请求

思路:设置并发请求限制,用队列存放请求,每次请求会先判断是否超出设置的最大并发请求数,当请求完成后,从队列中取出下一个请求,直到队列中的请求全部完成。

export class RequestQueue {
  constructor(concurrency = 6) {
    this.concurrency = concurrency; // 设置最大并发数,默认为6
    this.queue = []; // 存放请求的队列
    this.current = 0; // 当前正在执行的请求数
  }

  // 处理队列中的请求(出队)
  dequeue() {
    while (this.current < this.concurrency && this.queue.length) {
      this.current++;
      // 从队列中取出下一个请求并执行
      const requestPromiseFactory = this.queue.shift();
      requestPromiseFactory()
        .then(() => {
          // 成功的请求逻辑
        })
        .catch((error) => {
          // 失败
          console.log(error);
        })
        .finally(() => {
          this.current--;
          this.dequeue();
        });
    }
  }

  // 添加请求到队列中(入队)
  enqueue(requestPromiseFactory) {
    this.queue.push(requestPromiseFactory);
    this.dequeue();
  }
}

代码解释:

实际使用

const requestQueue = new RequestQueue(6); // 创建一个并发数为6的请求队列

// 模拟一个异步函数
sleep(fn) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(fn);
    }, 2000);
  });
},

// 生成测试请求
const queue = [...Array(20)].map((_, i) => () =>
  this.sleep(
    axios
      .get('/api/test' + i)
      .then(r => console.log(i, '成功'))
      .catch(e => console.log('失败', i))
  )
);

// 添加请求到队列中
for (let i = 0; i < queue.length; i++) {
  requestQueue.enqueue(queue[i]);
}

请求覆盖

场景:先后有A、B两个请求,A请求还未返回,B请求已经发起,并且B请求的结果比A先返回,那么A请求就会覆盖B请求的结果,正常要的结果是B的结果覆盖掉A请求的结果

可以用队列来维护请求的顺序,按照队列的顺序发起请求,但这有种“杀鸡用牛刀”的感觉,因为我们完全可以取消之前的请求,用最新的请求结果来赋值

可以通过以下方式解决请求覆盖的问题:

方法一:时序控制

let requestId = 0; // 全局标识

// 发送请求
function sendRequest() {
  const currentRequestId = ++requestId; // 递增全局标识

  // 发起请求
  axios.get('/api/data')
   .then(response => {
      // 判断当前请求是否是最新的请求(如果有新的请求那么requestId在新的请求会+1,比当前这个方法的curentRequestId的要大)
      if (currentRequestId >= requestId) {
        // 处理响应数据
        console.log(response.data);
      }
    })
   .catch(error => {
      // 处理错误
      console.error(error);
    });
}

方法二:取消旧请求

// 通过axios的cancelToken来取消请求

let cancelToken; // 取消请求的令牌

// 发送请求
function sendRequest() {
  // 取消旧请求
  if (cancelToken) {
    cancelToken.cancel();
  }

  // 创建新的取消请求的令牌
  cancelToken = axios.CancelToken.source();

  // 发起请求
  axios.get('/api/data', {
    cancelToken: cancelToken.token
  })
 .then(response => {
      // 处理响应数据
      console.log(response.data);
    })
 .catch(error => {
      // 处理错误
      console.error(error);
    });
}
// 自定义的取消请求函数
let lastCancel = null;
let cancelable = (req, callback) => {
  let cb = callback;
  req.then(res => {
    cb && cb(res);
  })
  let cancel = () => {
    cb = null;
  }
  return cancel;
}
let sendRequest() {
  lastCancel && lastCancel();
  lastCancel = cancelable(axios.get('/api/data'), res => {
    console.log(res);
  })
}

到此这篇关于前端请求并发和请求覆盖的解决方法的文章就介绍到这了,更多相关前端请求并发和请求覆盖内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文