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
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值