需求:原生实现并发请求
/**
* 批量请求
* @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)
})
直接看结果