前端API请求
# 前言
今天看了一篇的文章<前端API请求的各种骚操作>, 记录下。
并发控制
需求分析:
- 要发起10个请求才能获取全量数据
- 控制最多5个并发请求
文中主要使用Promise.all完成需求1,当请求数量达到限制时,使用 await Promise.race 来阻塞循环。
async function requestControl(taskLimit = 2, taskArray = []) {
const resultTaskArray = [];
const executingTaskArray = [];
while(taskArray.length) {
const taskPromise = taskArray.shift();
const resultPromise = taskPromise();
executingTaskArray.push(resultPromise);
resultTaskArray.push(resultPromise);
resultPromise.then(() => {
// 关键点,删除完成的请求
executingTaskArray.splice(executingTaskArray.indexOf(executingTaskArray), 1);
})
// 关键点,限制判断使用await 阻塞循环 发起新的请求
if (executingTaskArray.length >= taskLimit) {
await Promise.race(executingTaskArray)
}
}
// 最后返回全部结果
return Promise.all(resultTaskArray);
}
let i = 0;
function generateRequest() {
const j = ++i;
return function request() {
return new Promise(resolve => {
console.log(`r${j}...`);
setTimeout(() => {
resolve(`r${j}`);
}, 1000 * j * Math.random());
})
}
}
const requestPool = [generateRequest(), generateRequest(), generateRequest(), generateRequest()];
async function main() {
const results = await requestControl(3, requestPool);
console.log(results);
}
main();
不使用async await 版本
function requestControl(taskLimit = 2, taskArray = []) {
const resultTaskArray = [];
const executingTaskArray = [];
function dequeue() {
const taskPromise = taskArray.shift();
let _promise = Promise.resolve()
// 递归出口
if (!taskPromise) {
return _promise;
}
const resultPromise = taskPromise();
executingTaskArray.push(resultPromise);
resultTaskArray.push(resultPromise);
resultPromise.then(() => {
// 关键点,删除完成的请求
executingTaskArray.splice(executingTaskArray.indexOf(executingTaskArray), 1);
})
// 关键点,通过返回不同的promise 决定是否继续循环
if (executingTaskArray.length >= taskLimit) {
_promise = Promise.race(executingTaskArray)
}
// 递归
return _promise.then(dequeue);
}
// 最后返回全部结果
return dequeue().then(() => Promise.all(resultTaskArray))
}
总结
- 使用 await Promise.race 来阻塞循环;
- 函数里使用promise 进行递归循环;