实现链式延迟调用

234 阅读1分钟

实现链式延迟调用

面试题。

题目:

var o = new O();
o.print(1).setTimeout(1000).print(2).setTimeout(1000).print(3)

实现上面的O。

分析

这道题首先是要实现链式的调用,只要每次执行完成之后返回this,然后是延迟,等待上一个任务执行完成之后再执行下一个,遇到等待我们能想到的js种可以实现等待的:

  • setTimeout队列
  • setTimeout执行顺序
  • Promise.then
  • 队列

接下来我们以这几个思路来实现链式的延迟调用。

setTimeout队列

思路:根据setTimeout异步队列,js会先执行同步队列的代码,然后再去访问setTimout异步队列的代码,执行完一个剥离一个。

function O(){
    this.queue = []
    setTimeout(() => {
        this.then()
    })
}

O.prototype.print = function(num) {
    this.queue.push(() => {
        console.log(num)
        this.then()
    })
    return this
}
O.prototype.setTimeout = function(timer) {
    this.queue.push(() => {
        setTimeout(() => {
            console.log(timer)
            this.then()
        },timer)
    })
    return this
}
O.prototype.then = function() {
    const task = this.queue.shift()
    task && task()
}

setTimeout执行顺序

思路:根据setTimeout根据设置的时长不同,来达到延迟调用。

function O(){
    this.timer = 0
}

O.prototype.print = function(num) {
    setTimeout(() => {
        console.log(num)
    },this.timer)
    return this
}
O.prototype.setTimeout = function(timer) {
    this.timer += timer
    setTimeout(() => {
        console.log(timer)
    },this.timer)
    return this
}

Promise.then

思路:链式调用就像我们常用的promise.then一样,我们以这个为思路,做一个promise队列,链式调用需要上一个执行完毕,才能接着执行下一个,所以把print放到初始的Promise的then中,把setTimeout放到print的then中。

function O(){
    this.queue = new Promise(res => res())
}
O.prototype.print = function(num) {
    this.queue = this.queue.then(() => {
        return new Promise(reslover =>{
            console.log(num)
            reslover();
        })
       
   })
    return this
}
O.prototype.setTimeout = function(timer) {
    this.queue = this.queue.then(() => {
     return new Promise(reslover =>{
            setTimeout(() => {
                 console.log(timer)
                 reslover();
            },timer)
        })
       
   })
    return this
}

队列

function O(){
    this.queue = [] // 存放需要执行的代码
    this.excuteLock = false 
}
O.prototype.print = function(num) {
    this.queue.push(() => {
         return new Promise(reslover => {
            console.log(num)
            reslover();
        })
    })
    this.runNext()
    return this
}
O.prototype.setTimeout = function(timer) {
    this.queue.push(() => {
        return new Promise(reslover => {
            setTimeout(() => {
                 console.log(timer)
                 reslover();
            },timer)
        })
    })
    this.runNext()
    return this
}
O.prototype.runNext = async function(timer) {
    if(this.queue.length && !this.excuteLock){
        this.excuteLock = true
        const task = this.queue.shift()
        await task()
        this.excuteLock = false
        this.runNext()
    }
}

最后

以上就是本篇文章分享的全部内容了。

这里是 lydialy。喜欢的掘友们可以点赞关注点个收藏~