原生js实现并发请求

503 阅读1分钟

需求:原生实现并发请求

/**
 * 批量请求
 * @param  {String[]} urls 所有的请求地址
 * @param  {Number} max 最大并发数
 * @param  {Function} step 每一个请求成功后的回调函数
 * @param  {Function} success 所有请求完成的回调函数
 */
function request(urls, max, step, success)
{
}

1、现有大量请求发送到后台,所有的请求地址放在了urls中通过max控制并发数。
2、同时存在的最大请求数不能超过这个数。
3、考虑大量请求中有失败的情况。

实现

模拟一个ajax请求

/**
 * 模拟ajax请求
 * @param  {String} url 请求地址
 */
 function ajax(url)
{
    return new Promise((resolve, reject)=>{
        setTimeout(() => {
            const success = {
                req: url,
                res: `成功响应内容${url}`
            }
            const error = {
                req: url,
                res: `失败响应内容${url}`
            }
            Math.random() > 0.1 ? resolve(success): reject(error) // 0.1请求概率会失败
        }, Math.floor(Math.random() * 1000) + 1000);
    })
}
 

批量请求

/**
 * 批量请求
 * @param  {String[]} urls 所有的请求地址
 * @param  {Number} max 最大并发数
 * @param  {Function} step 每一个请求成功后的回调函数
 * @param  {Function} success 所有请求完成的回调函数
 */
function request(urls, max, step, success)
{
    return new Promise((resolve, reject) => {
        let _urls = [...urls] // 所有请求的urls
        let _ress = {} // 每一次请求成功或失败的对象
        let stackNum = 0; // 当前请求数
        let _rsl = []; // 存放所有返回内容
        let addXhr = function () {
            if (stackNum >= max || _urls.length == 0) return;
            const __path = _urls.shift(); // 取出数组中第一个url
            stackNum ++;
            console.log(`${__path} 开始!`)
            ajax(__path).then(res => {
                _ress[__path] = res;
                step(`${__path} 结束,成功!`)
                stackNum --;
                if (stackNum == 0 && _urls.length == 0) {
                    // 所有请求全部返回完毕
                    for (let i=0;i<urls.length;i++) {
                        _rsl.push(_ress[urls[i]])
                    }
                    success(_rsl) // 函数返回
                    resolve(_rsl) // promise返回
                } else {
                    addXhr();
                }
            }).catch(err => {
                _ress[__path] = err;
                step(`${__path} 结束, 失败!`)
                stackNum --;
                addXhr();
            })
        }
        while (stackNum < max) {
            addXhr();
        }
    })
}

测试模拟

request([1,2,3,4,5,6,7,8,9,10,11,12,13], 2, function (step) {
    console.dir(step)
}, function(success) {
    console.dir(success)
})

直接看结果

image.png