方案1: 请求队列
export default class RequestQueue {
constructor(maxConcurrent) {
this.maxConcurrent = maxConcurrent;
this.currentConcurrent = 0;
this.queue = [];
this.requestId = 0;
}
add(request, meta = {}) {
return new Promise((resolve, reject) => {
const id = ++this.requestId;
this.queue.push({
id,
request: () => request().then(res => ({
id,
res
})),
resolve,
reject,
meta,
});
this.processQueue();
})
}
processQueue() {
while (this.queue.length > 0 && this.currentConcurrent < this.maxConcurrent) {
const task = this.queue.shift();
this.currentConcurrent++;
task.request()
.then(({
id,
res
}) => {
task.resolve({
id,
meta: task.meta,
data: res
});
})
.catch(task.reject)
.finally(() => {
this.currentConcurrent--;
this.processQueue();
});
}
}
}
组件调用
import request from '@/utils/request.js';
import RequestQueue from '@/utils/RequestQueue.js';
const requestQueue = new RequestQueue(3);
const urls = [
{
url: '/slider/getSliders',
method: '',
data: '',
id: 1,
reqType: 'getSliders'
},
{
url: '/course/mostNew',
method: 'post',
data: newCoursePageInfo,
id: 2,
reqType: 'mostNew'
},
{
url: '/course/search',
method: 'post',
data: interestCoursePageInfo,
id: 3,
reqType: 'search'
}
];
const fetchData = ({ url, method, data }) => {
return request(url, data, method).then((res) => {
return res;
});
};
const requests = urls.map((url) => () => fetchData(url));
onLoad(() => {
Promise.all(requests.map((req, idx) => requestQueue.add(req, { originalIndex: idx, reqType: urls[idx].reqType }))).then((results) => {
results.forEach(({ meta, data }) => {
switch (meta.reqType) {
case 'getSliders':
swiperList.value = data.list;
break;
case 'mostNew':
interestCouseInfo.value.push(...data.pageInfo.list);
break;
case 'search':
newCourseInfo.value = data.pageInfo.list.slice(3, 9);
break;
}
console.log(`请求${meta.originalIndex}(${meta.reqType})结果:`, data);
});
});
});
说明:
- reqType: 请求唯一标识符,用于将并行发出的请求与响应回的数据对应上
- request: 对axios做的二次封装,函数fetchData 发出的请求就好比在api文件中的请求函数
只需在 对象urls变动url(id可不需要,唯一标识符必须) 和在 results赋值即可