15行代码实现一个带并发数限制的fetch请求函数

原题

读题

  1. 批量请求
  2. 可控制并发度
  3. 全部请求结束,执行 callback

解题

方案一: 递归

function sendResquest(urls, max, callback) {
    let urlsCopy = [... urls];//防止影响外部urls变量
    function request() {
        function Handle () {
            count--;
            console.log('end 当前并发数为: '+count);
            if(urlsCopy.length) {//还有未请求的则递归
                request();
            } else if (count === 0) {//并发数为0则表示全部请求完成
                callback()
            }
        }
        count++;
        console.log('start 当前并发数为: '+count);
        //请求
        fetch(urlsCopy.shift()).then(Handle).catch(Handle);
        //并发数不足时递归
        count < max && request();
    }
    let count = 0;//几率并发数
    request();
}

方案二: Promise

function sendResquest(urls, max, callback) { 
    let pending_count = 0, //并发数
    idx = 0;//当前请求的位置

    while (pending_count < max) { 
        _fetch(urls[idx++])
    } 
 
    async function _fetch(url) { 
        if (!url) return; 
        pending_count++; 
        console.log(url + ':start','并发数: '+pending_count); 
        await fetch(url) 
        pending_count--; 
        console.log(url + ':done','并发数: '+pending_count); 
        _fetch(urls[idx++]); 
        pending_count || callback && callback()
    } 
}

全部代码

//递归方式
function handleFetchQueue(urls, max, callback) {
    let urlsCopy = [... urls];//防止影响外部urls变量
    function request() {
        function Handle () {
            count--;
            console.log('end 当前并发数为: '+count);
            if(urlsCopy.length) {//还有未请求的则递归
                request();
            } else if (count === 0) {//并发数为0则表示全部请求完成
                callback()
            }
        }
        count++;
        console.log('start 当前并发数为: '+count);
        //请求
        fetch(urlsCopy.shift()).then(Handle).catch(Handle);
        //并发数不足时递归
        count < max && request();
    }
    let count = 0;//几率并发数
    request();
}

//Promise方式
function sendResquest(urls, max, callback) { 
    let pending_count = 0, //并发数
    idx = 0;//当前请求的位置

    while (pending_count < max) { 
        _fetch(urls[idx++])
    } 
 
    async function _fetch(url) { 
        if (!url) return; 
        pending_count++; 
        console.log(url + ':start','并发数: '+pending_count); 
        await fetch(url) 
        pending_count--; 
        console.log(url + ':done','并发数: '+pending_count); 
        _fetch(urls[idx++]); 
        pending_count || callback && callback()
    } 
}


//验证
let urls = Array.from({length: 10}, (v, k) => k);

let fetch = function (idx) {
    return new Promise(resolve => {
        let timeout = parseInt(Math.random() * 1e4);
        setTimeout(() => {
            resolve(idx)
        }, timeout)
    })
};

let max = 4;

let callback = () => {
    console.log('run callback');
};
//执行
sendResquest(urls, max, callback)

 

  • 1
    点赞
  • 6
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

CalmHarbin

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值