FE-Interview
FE-Interview copied to clipboard
实现一个多并发的请求
let urls = ['http://dcdapp.com', …];
/*
*实现一个方法,比如每次并发的执行三个请求,如果超时(timeout)就输入null,直到全部请求完
*batchGet(urls, batchnum=3, timeout=3000);
*urls是一个请求的数组,每一项是一个url
*最后按照输入的顺序返回结果数组[]
*/
扫描下方二维码,获取答案以及详细解析,同时可解锁800+道前端面试题。

<!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>
</head>
<body>
<script>
// let urls = ['http://dcdapp.com',];
/*
*实现一个方法,比如每次并发的执行三个请求,如果超时(timeout)就输入null,直到全部请求完
*batchGet(urls, batchnum=3, timeout=3000);
*urls是一个请求的数组,每一项是一个url
*最后按照输入的顺序返回结果数组[]
*/
function batchGet(urls, batchnum = 3, timeout = 3000) {
return new Promise((resolve) => {
let results = Array(urls.length).fill()
let fetchingCount = 0
let restCount = urls.length
let finishCount = 0
let i = 0
const request = () => {
while (fetchingCount < batchnum && restCount) {
fetchingCount++
restCount--
let innerIndex = i
let promises = [
fetch(urls[innerIndex]).then((res) => {
return res
}),
new Promise((resolve, reject) => {
let timer = setTimeout(() => {
reject(null)
clearTimeout(timer)
timer = null
}, timeout)
})
]
console.log(`🌐 开始请求: ${urls[innerIndex]}`);
Promise.race(promises).then((res) => {
console.log(`✔ url-${urls[innerIndex]} %c 成功获取到数据:${res}`, 'background:green;color:#fff;');
results[innerIndex] = res
}).catch(errData => {
console.log(`❌ url-${urls[innerIndex]} %c 超时`, 'background:red;color:#fff;');
results[innerIndex] = errData
}).finally(() => {
fetchingCount--
finishCount++
if (finishCount === urls.length) {
resolve(results)
}
request()
})
i++
}
}
request()
})
}
// 重新定义 fetch 方便测试
function fetch(url) {
const timeout = Math.floor(Math.random() * 1000 * 5)
return new Promise((resolve) => {
setTimeout(() => {
resolve(timeout)
}, timeout)
})
}
const urls=Array(20).fill().map((_,index)=>`https://baidu.com--${index}`)
batchGet(urls, 5).then((results) => console.log('👉 请求结果:', results));
</script>
</body>
</html>
function delayPromise(timeout) {
return new Promise((resolve, reject) => {
setTimeout(resolve, timeout);
});
}
function timeoutPromise(promise, ms) {
const timeout = delayPromise(ms).then(() => {
return null;
});
return Promise.race[timeout, promise];
}
function fetch(url) {
return new Promise(async (resolve, reject) => {
try {
const res = await fetch(url);
resolve(res);
} catch (err) {
reject(err);
}
});
}
function batchGet(urls,batchnum=3, timeout=3000 ) {
const result = [];
const chunkLen = Math.ceil(urls.length / batchnum);
for (let i = 0; i < chunkLen; i++) {
const curUrls = urls.slice(batchnum * i, batchnum * (i + 1));
const fetchs = curUrls.map((url) => fetch(url));
const pAll = Promise.all(fetchs);
const curRes = timeoutPromise(pAll, timeout);
if (!curRes) {
return null;
}
result.push(...curRes);
}
return result;
}