likes
comments
collection
share

面试官问:如果有100个请求,你咋办?

作者站长头像
站长
· 阅读数 17

之前看到一篇文章的评论,一位仁兄说:“谁会傻不拉几的一次性发起 100 多条请求的?”

一看这位仁兄就是对大文件的分片请求没有任何概念。

如果有一个1.5G的文件,不管是上传服务器,还是下载到本地,如果不分片,请问这位仁兄你咋办?难道你要一次性1.5G 把它请下来?

其实大文件请求很多人都用过,为什么不知道内部怎么搞的呢?主要问题就是咱们做的项目都是成熟项目,只需要调用相应的接口,运用相应的方法就成功了,完全没有去刨根问底,所以你觉得即使再大的文件,也是一次性请求下来。

之前在大文件分块上传的文章里面已经用过异步并发了

面试官问:如果有100个请求,你咋办?

现在再带大家专门研究下这个东西。

异步并发数的代码原理有两种:

一个是:执行队列里面的异步请求数达到6的时候,把他们放到Promise.all() 或者 Promise.allSettled()里面一起并发执行,执行完以后清空数组,继续往里面加六个,直到最后结束。它的精髓是用await去暂停while等拿到这6个结果以后,再去清空数组。

另一个是:在执行数组里面加入六个请求,只要有一个请求获得了结果,那就把他从数组里面清除掉,然后再加入一个新的异步请求进来。它主要利用的是函数的递归处理。

还有一个就是第三方库,不管第三方库再怎么好用,不能因为有他们的存在,我们就不用去探索它的封装原理,毕竟那是他们的理解,不是我们的,我们要做的是,在他们的基础上,封装出更好的,更完美的,更适合自己的库出来。

下面就对这 2 种异步并发代码做简单的书写:

第一种是: Promise.allSettled()

每六个六个的发送请求,但是它的弊端是:如果有一个请求阻塞了,那这一组就要等着,直到它拿到响应数据为止。

  // 每3个执行完以后,清空队列,继续加3个,直到所有的请求全部执行完
  const max = 6; // 并发请求数量
  let taskPool = []; // 请求队列
  const total = 12; // 一共有17个异步请求
  let index = 0;

  // 异步请求
  const asyncFn = (index)=>{
      return new Promise((resolve)=>{
          setTimeout(()=>{
              console.log("定时")
              resolve(`第 ${index} 个成功了!`)
          }, 500)
      })
  }

 async function fn(){
      while(index < total){
          if(taskPool.length < max){
              taskPool.push(asyncFn(index))
          } 
          
          if(taskPool.length === max) {
              await Promise.allSettled(taskPool).then((res)=>{
                  console.log(res);
                  taskPool=[]
              })
          }

          index ++;
      }
  }
  fn()

上面代码有个逻辑bug,大家可以动动手找处理,补好,记得和我分享下你的解决方案呀!测试如下:

面试官问:如果有100个请求,你咋办?

第二种是: 利用递归法

其实很多时候我们想要做的是:请求池里面有6个请求,然后谁执行结束以后,就去执行递归函数,再往数组里面加新的请求。

const arr = [];
for (let i = 0; i < 100; i++){
    arr.push(() => new Promise((resolve) => {
        setTimeout(() => {
            console.log('done', i);
            resolve();
        }, 100 * i);
    }));
};

const run = (arr, max) => {
    const runingTask = []; //请求池
    
        // 当请求总数小于最大请求数,全部加入,然后循环执行。
        while (runingTask.length < max && arr.length) {
            // 利用循环,先将第前6个加入进来
            runingTask.push(arr.shift());
        }

        // 当请求总数大于最大请求数
        while (runingTask.length) {
            runingTask.shift()().finally(() => {
                run(arr, max);
            });
        }
 
};

run(arr, 6);

执行结果如下:

面试官问:如果有100个请求,你咋办?

它的数据一个一个出来的。

第三种是: 第三方库:

此外,还有一些第三方库可以使用,例如async.jsp-limit等。p-limit是一个专门用于控制Promise并发的小型库。可以在p-limit文档中找到更多信息和示例。

转载自:https://juejin.cn/post/7393525123766140943
评论
请登录