开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情>>
记得很久之前,有次面试。面试官问了个问题,怎么按顺序发送100个请求?
那时候,我首先想到的是,在每次请求回来之后的回调函数里面发送下一个请求。
现在想来,虽然这样是可以做到的,但是很不优雅。那么怎样才能更优雅的来做这个事情呢?
async/await
首先我们确保这些http请求都是通过Promise函数封装过的。然后通过async/await来阻塞循环,来达到这个目的:
// for 循环
const funList = [fun1,fun2,...,fun100];
async function run1(){
for(let i = 0;i< funList.lenght;i++ ){
await funList[i]();
}
}
// while 循环
async function run2(){
let i =0;
while(i<funList.lenght){
await funList[i]();
i++;
}
}
PS: Promise.all是同步的,不能进行one by one的执行效果。
尽管循环阻塞能够达到要求,但是在await的过程中,主线程是阻塞状态,会严重影响浏览器的渲染。
所以,更好的方法应该还是回调的方式,只是应该更优雅的进行回调,那就是链式回调。
我们可以先将函数列表做成一个链表模式:
// Promose函数列表
const funList = [fun1,fun2,...,fun100];
// 声明链表的头部和尾部
let funChainHead = null, funChainTail = null;;
// 构造链表
funList.forEach((fun,i) => {
if(i === 0){
funChainTail = { next:null, value:fun};
funChainHead = funChainTail;
} else {
funChainTail.next = { next:null, value:fun};
funChainTail = funChainTail.next;
}
})
// 重置链表尾部
funChainTail = funChainHead;
// 递归执行函数
funciont run(funChainTail){
if(!funChainTail) return;
funChainTail.value().then(() => {
run(funChainTail = funChainTail.next);
})
}
如上,链式调用接口请求,这样不会阻塞主进程的运行。虽然还是回调的模式,但是优雅的多。
链表在实际工作中的作用还有更多,也是非常有意思的一种数据结构。以后,我还会分享更多关于链表的内容。
如果你有更好的解决方案,请在评论中留下你的方案。