问题描述
先看下面一段代码:
function main(n) {
for (let i = 1; i <= n; i++) {
request(`第${i}个请求`, getRandomTime(500, 2000));
}
}
function getRandomTime(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function request(text, time) {
new Promise((resolve, reject) => {
setTimeout(() => { resolve(text) }, time);
}).then(res => {
console.log(res);
})
}
main(5);
这段代码的意思为,同时发送多个请求,每个请求都需要0.5s-2s的等待时间才能返回结果。
运行上述代码,结果如下:
由于每个请求需要等待的时间是不确定的,进而如果我们想得到最后一次发送请求的数据,此时应该如何处理呢?(类似于实际应用中同一时间向后端请求多次,但是我们只需要得到最后一次请求的结果即可)
解决问题
解决思路:由于请求的等待时间是不确定的,所以我们无法直接得知最后一次请求将会是第几次返回。如果此时我们为每组请求都赋予一个请求id,等到它的数据返回时,那么我们就可以直接通过其请求id来判断它是第几个请求。
look my code:
let globalId = 0;
function main(n) {
for (let i = 1; i <= n; i++) {
request(`第${i}个请求`, getRandomTime(500, 2000));
}
}
function getRandomTime(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function request(text, time) {
globalId++;
const id = globalId;
new Promise((resolve, reject) => {
setTimeout(() => { resolve(text) }, time);
}).then(res => {
if (id === globalId) {
console.log(res);
}
})
}
main(5);
运行上述代码,结果如下:
果不其然,这次我们如愿精准捕获到最后一次请求的返回数据。
问题升级
如果我们还想要按照请求发送的顺序得到返回结果的请求,那么又该如何处理呢?
有了上面的全局id以及请求id的思路,此时我们只需要再维护一个保存数据的数组即可,让它依据请求id来记录每次返回的结果。
代码如下:
let globalId = 0;
let container = null;
let count = 0;
function main(n) {
container = new Array(n).fill(0);
for (let i = 1; i <= n; i++) {
request(`第${i}个请求`, getRandomTime(500, 2000));
}
}
function getRandomTime(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function request(text, time) {
globalId++;
const id = globalId;
new Promise((resolve, reject) => {
setTimeout(() => { resolve(text) }, time);
}).then(res => {
container[id - 1] = res;
count++;
if (count === 5) {
console.log(container);
}
})
}
main(5);
运行上述代码,结果如下:
到此为止,一段随机时间顺序的异步请求的结果终于被我们有序的记录下来。
结语
又一道有意思的工作问题被解决了,如果大家有啥疑问或者更为精妙的解决方案,欢迎评论区留言。