按顺序发送请求的解决方案

300 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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);
    })
}

如上,链式调用接口请求,这样不会阻塞主进程的运行。虽然还是回调的模式,但是优雅的多。

链表在实际工作中的作用还有更多,也是非常有意思的一种数据结构。以后,我还会分享更多关于链表的内容。

如果你有更好的解决方案,请在评论中留下你的方案。