利用 promise 如何模拟实现限制最大并发请求的案例?

mikechen
  • 556

RT 求大佬一份 promise 实现的最大并发请求的 demo
最好能说明下应用场景,可以打印出直观的效果~

回复
阅读 407
3 个回答
✓ 已被采纳

这个题其实网上挺多实现的。npm中有很多实现这个功能的第三方包,比如async-pool、es6-promise-pool、p-limit,也可以直接拿来用。

这个题的重点就是把任务放在队列里(function 或者基础类型、url、对象等等),然后执行,执行完了就从队列中取一个。

image.png

我就用一个字符串当作条件了。然后每次执行和执行完了都会从队列中重新取一个。

list = new Array(20).fill('1').map((v,i)=>`https://www.lilnong.top/cors/${i}`);
max = 5;
currentTaskNum = 0;

function run(){
    if(currentTaskNum < max && list.length){
        var curTask = task(list.shift());
        if(curTask && curTask.then){
            currentTaskNum++;
            curTask.then(v=>{
                console.log(Date.now(), 'end')
                currentTaskNum--;
                run()
            })
        }
        run()
    }
}

function task(url){
    console.log(arguments, Date.now(), 'start')
    return fetch(url)
}

run()
已参与了 SegmentFault 思否「问答」打卡,欢迎正在阅读的你也加入。

吐槽一下更新,没一下子找到答案在哪回复……

可以看一下楼上所说的几个库的实现,拿async-pool来说,是通过维护正在执行的任务列表和限制数做长度比较,如果超过限制,通过Promise.race竞速,将完成的任务删除、添加新任务。

场景:大文件分片上传……

这是我以前写的对 Promise.map 的实现, 可以看看。

Promise.map = function (data, mapfun, options) {
  return new Promise((resolve, reject) => {
    var promiseArr = [];
    var concurrency = options ? +options.concurrency : 0;
    //无并发控制
    if (concurrency == 0 || concurrency != concurrency) {
      for (var i in data) {
        promiseArr.push(mapfun(data[i], i, data));
      }
      Promise.all(promiseArr).then(resolve, reject);
      return;
    }
    var k = 0;
    var keys = (function () {
      var ks = [];
      for (var k in data) {
        ks.push(k);
      }
      return ks;
    })();
    function next() {
      if (k < keys.length) {
        var key = keys[k];
        var promise = Promise.resolve(mapfun(data[key], key, data)).then(
          function (v) {
            next();
            return v;
          },
          reject
        );
        promiseArr.push(promise);
        concurrency--;
        k++;
      } else {
        Promise.all(promiseArr).then(resolve, reject);
      }
    }
    do {
      next();
    } while (concurrency > 0 && k < keys.length);
  });
};
function delay(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      console.log(ms);
      resolve(ms);
    }, ms);
  });
}

Promise.map([300,100,200,700,400],delay,{concurrency:1})
// Promise.map([300,100,200,700,400],delay,{concurrency:3})
你知道吗?

宣传栏