duuliy

js请求限流的2种方式

2022-1-29

最多2个请求同时并发
  let queue = []
    const limit = 2
    let count = 0

    const interface = (cont) => {
      return () => new Promise((res, rej) => {
        setTimeout(() => {
          console.log(cont)
          res()
        }, 500)
      })
    }

    const main = () => {
      for (let i = 0; i < 10; i++) &#123;
        queue.push(interface(i))
      &#125;

      const helper = () => &#123;
        // debugger
        if (count > limit || !queue.length) return void (0)
        count++
        // console.log(queue.shift())
        queue.shift()().then(() => &#123;
          count--
          helper()
        &#125;)
      &#125;

      for (let i = 0; i < limit; i++) &#123;
        helper()
      &#125;

    &#125;

    main()

    //上面的达到了效果但是总觉得有点讨巧,2根管道依次执行异步,也最简单。
第二种方法
 const interface2 = (cont) => new Promise((res, rej) => &#123;
      setTimeout(() => &#123;
        res(cont)
      &#125;, 500)
    &#125;)


    const main2 = () => &#123;
      const helper = async (fn) => &#123;
        // debugger
        if (count >= limit) &#123;
          await new Promise((resolve) => &#123;
            queue.push(resolve)
          &#125;)
        &#125;
        count++
        await fn()
        count--
        console.log(queue)
        if (queue.length > 0) &#123;
          queue.shift()()
        &#125;
      &#125;

      //当第一个helper内部(上下文) await fn()没执行完,第二个helper就进入了,直到遍历完for
      for (let i = 0; i < 10; i++) &#123;
        helper(() => &#123;
          return interface2(i).then(res => &#123;
            console.log(res)
          &#125;)
        &#125;)
      &#125;
    &#125;

    main2()

    //上面通过promise来控制异步,同步时,先执行前2个fn的setTimeOut,然后把queue加8个微任务。 当遍历完成,开始执行等待的队列上下文,顺序为:
    //fn的then =>释放queue.shift()=>0=>fn的then =>释放queue.shift()=>1=> !!! 由于第三个开始要等待await newPromise的返回值,所以没在之前的
    //队列里面执行fn的setTimeOut,所以这里要等待500ms才会打印2,由于i 0和1释放了2个queue里面的微任务queue.shift()() , 所以2和3中的2已经在0的时候
    //执行了fn的setTimeOut, 然而0和1结束之后, 只需要等待3的fn的setTimeOut => 后续遍历依照上诉逻辑