实现一个带并发数限制的fetch请求函数

1,201 阅读1分钟

整理了一道前端字节的面试题,分享给大家。如有问题,欢迎指正!

题目描述:

请实现以下函数,可以批量请求数据,所有的url地址在参数urls中,通过max参数控制请求并发数,当所有请求结束后,需要执行callback回调函数。发请求的函数直接使用fetch即可。

function handleFetchQueue(urls, max, callback){
    // TODO
}

思路

1、开始并发max个请求(如总数不超过max按照实际总数来)
2、每一个请求结束后开启下一个请求
3、哎,这是不是得用到递归啊,没错!
4、每个请求的结果无论成功还是失败还是存到results数组中吧,万一callback要用呢
5、啥时候执行回调函数呢,这个统计一下成功失败的数量等于url总数就行,也可以直接用results数组的长度判断

开写代码

function handleFetchQueue (urls, max, callback) {
    const originUrlCount = urls.length // 原始url的数量
    const results = []
    // 1、同时发起max个请求
    for (let i = 0; i < urls.length && i < max; i++) {
        handleOneRequest(urls.shift())
    }
    function handleOneRequest (url) {
        console.log('start', url)
        fetch(url).then(res => {
            results.push(res)
        }).catch(err => {
            results.push(err)
        }).finally(() => {
            console.log('end', url)
            // 2、完成1个请求,队列中随便退出一个,加入下一个
            if (urls.length) {
                handleOneRequest(urls.shift())
            }
            if (results.length === originUrlCount) {// 请求全部完成
                callback(results)
            }
        })
    }
}
        

完整测试

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        function handleFetchQueue (urls, max, callback) {
            const originUrlCount = urls.length // 原始url的数量
            const results = []
            // 1、同时发起max个请求
            for (let i = 0; i < urls.length && i < max; i++) {
                handleOneRequest(urls.shift())
            }
            function handleOneRequest (url) {
                console.log('start', url)
                fetch(url).then(res => {
                    results.push(res)
                }).catch(err => {
                    results.push(err)
                }).finally(() => {
                    console.log('end', url)
                    // 2、完成1个请求,队列中随便退出一个,加入下一个
                    if (urls.length) {
                        handleOneRequest(urls.shift())
                    }
                    if (results.length === originUrlCount) {// 请求全部完成
                        callback(results)
                    }
                })
            }
        }
 
        handleFetchQueue([
            "http://baidu.com1",
            "http://bytedance.com2",
            "http://taobao.com3",
            "http://baidu.com4",
            "http://bytedance.com5",
        ], 2, (res) => {
            console.log("全部执行完毕", res)
        })
    </script>
</head>
</html>

输出

image.png

参考博客

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