字节一面的一道好题:如何实现异步链式调用

Posted hans774882968

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字节一面的一道好题:如何实现异步链式调用相关的知识,希望对你有一定的参考价值。

字节一面出了一道好题:实现一个异步链式调用的效果:new CodeMan().eat("lunch").sleep(10).eat("dinner")sleep(10)表示要异步地等待10s以后执行后面的内容。

面试官只给了一个关键字的提示:队列。我是那个百思不得其解啊!

面试后,我想了想,调用阶段(是同步任务,会先执行)先用一个队列把任务收集起来(这里把eat和sleep统称为”任务“),然后用”宏任务在同步任务执行完以后才执行“这个特性,来搞一个”假递归“,即当前任务执行完后再把下一个任务扔进宏任务队列。

而第一个任务,用setTimeout(process,0)调用,因为以上特性,所以它会在收集完毕以后才执行。

于是我们抽象出一个process函数,它的工作是:执行当前的宏任务。

更新:发出文章后看到前人的实现,感觉比我这个做法复杂些……

代码

function CodeMan(){
    let EAT = Symbol(),SLEEP = Symbol()
    function Task(type,arg){
        this.type = type
        if(type === EAT) this.food = arg
        else this.time = arg
    }
    let q = []
    this.eat = (food) => {
        q.push(new Task(EAT,food))
        return this
    }
    this.sleep = (time) => {
        q.push(new Task(SLEEP,time*1000))
        return this
    }
    let process = () => {
        if(!q.length) return
        let u = q.shift()
        if(u.type === EAT){
            console.log(u.food)
            setTimeout(process,0)
        }
        else{
            setTimeout(process,u.time)
        }
    }
    setTimeout(process,0)
}
new CodeMan().eat("lunch").sleep(2).eat("dinner").sleep(2).eat('breakfast')

以上是关于字节一面的一道好题:如何实现异步链式调用的主要内容,如果未能解决你的问题,请参考以下文章

字节跳动一面(凉)

链式调用就是promise的优点吗?

字节一面凉经

一道阿里/字节真题理解前端异步编程

解析promise链式调用

字节一面:如何用 UDP 实现可靠传输?