字节跳动面试:实现一个LazyMan函数

博客围绕JavaScript中实现一个可链式调用且函数能阻塞后续链式调用的类展开。指出用Promise或直接延时调用实现阻塞是误区,会增加代码难度且不一定能实现功能。最后提出可借鉴Promise用任务队列实现阻塞,只需依次执行任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现一个类,最终效果:

  • 可以链式调用
  • sleep() 函数会阻塞后面的链式调用
const lazyMan = new LazyMan('jack')
lazyMan.eat('apple').sleep(5000).eat('hamburger').sleep(3000).eat('pear')
/*
最终结果:
    My named jack
    I am eatting apple
    I am sleeping...
    after 5000 ms
    I am eatting hamburger
    I am sleeping...
    after 3000 ms
    I am eatting pear
*/

sleep函数

正常的 sleep 函数,如果是为了链式调用 Promise 可以这样写

function sleep(time) {
    return new Promise((resolve)=> {
        setTimeout(() => {
            resolve()
        }, time)
    })
}

但是这里如果为了实现阻塞链式调用而使用 Promise 的方式或者直接延时调用来实现,实际上是一个误区,会给代码增加很多难度,而且还不一定可以实现其功能

class LazyMan {
    constructor(name) {
        this.name = name
        this.task = []      // 任务队列
        console.log(`My named ${name}`)
    }
    sleep(time) {
        console.log(`I am sleeping...`)
        setTimeout(() => {
            console.log(`after ${time} ms`)
            return this
        },time)
    }

    eat(food) {
        console.log(`I am eatting ${food}`)
        return this
    }
}

const lazyMan = new LazyMan('jack')
lazyMan.sleep(5000).eat('apple')    //  property 'eat' of undefined

上面代码中,链式调用并不会主动去阻塞,延时 return this 并不会阻塞链式调用往下进行,因此调用到 eat('apple') 时,由于没有及时的返回 this,自然没有 eat 方法,所以就报错了

这个时候想到 Promise 的实现是用一个任务队列来进行阻塞的,可以也使用这样的方式,与 Promise 不同的是,实现这个并没有那么多的判断条件,只需要将每个任务执行完然后继续执行下一个任务就行

class LazyMan {
    constructor(name) {
        this.name = name
        this.task = []      // 任务队列
        console.log(`My named ${name}`)

        // 这里使用异步调用next()是为了确保所有链式调用都被添加到task[]才开始执行任务
        setTimeout(() => {
            this.next()
        })
    }

    sleep(time) {
        this.task.push(() => {
            console.log(`I am sleeping...`)
            setTimeout(() => {
                console.log(`after ${time} ms`)
                this.next()
            },time)
            
        })
        return this
    }

    eat(food) {
        this.task.push(() => {
            console.log(food)
            this.next()
        })
        return this
    }

    next() {
        let fn = this.task.shift()
        fn && fn()  // if(fn) fn()
    }


}

const lazyMan = new LazyMan('jack')
lazyMan.eat('apple').sleep(5000).eat('hamburger').sleep(3000).eat('pear')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值