• 现有一个 POST 接口:https://xxx.com/students,每次请求只能返回 10 个学生的课程成绩 如下, 该接口有一定概率请求失败 不可忽略:Response Status Code 500,Body 为空。
JSON: [
{ name: ‘张三’, score: 99, time: ‘2021-12-22’ },
{ name: ‘李四’, score: 60, time: ‘2021-12-12’ },
{ name: ‘王五’, score: 77, time: ‘2021-11-08’ },
… ]
要求:
实现一个函数,总共需获得 100 个成绩大于 90 分,且时间在2021年12月3日之后的学生的课程成绩,并按各自成绩从大到小排列返回。(可直接使用 fetch 或 axios)
提示:
○ 浏览器最多可以有 6 个并行的网络请求
○ 尽可能在更短的时间内,运行完成得到结果
○ 尽可能用最少的请求次数
let i = 0
let list = []
function rightTime(time) {
// 时间大于12月03日的时间返回true
}
async function fetchStudents() {
// *******************************实现相应逻辑******************************************
// cancelToken其实就是用来取消ajax请求
// 在真实项目中,当路由已经跳转,而上一页的请求还在pending状态,如果数据量小还好,数据量大时,跳到新页面,旧的请求依旧没有停止,这将会十分损耗性能,这时我们应该先取消掉之前还没有获得相应的请求,再跳转页面。
const source = axios.CancelToken.source();
const query = function query() {
return axios.post('https://xxx.com/students', null, { cancelToken: source.token })
.then(response => response.data);
};
/**封装可取消的axios 请求*/
const fetchStudentsAxios = function fetchStudents() {
return new Promise(resolve => {
// 创建6个工作区同时进行
let works = new Array(6).fill(null),
values = [],
flag = false;
works.forEach(() => {
// 每个工作区都是获取学生信息;当此任务执行完(不论成功还是失败),继续去获取学生信息..
const next = async () => {
if (flag) return;
// 当values存储的结果够100个后,就无需再发请求(取消正在发送的请求)
if (values.length >= 100) {
resolve(values.slice(0, 100));
source.cancel();
flag = true;
return;
}
try {
let value = await query();
value = value.filter(item => {
return item.score >= 90 && (new Date(item.time) - new Date('2021-12-03')) > 0;
});
values = values.concat(value);
} catch (_) { }
next();
};
next();
});
});
};
/**发送请求*/
let res = await axios.post(url, { data: { pageNum: i + 1 } })
list = list.cancat(...res.data.filter(item => {
return item.score > 90 && rightTime(item.time)
}))
if (list.length >= 100) {
return list
} else {
return fetchStudentsAxios()
}
}