实现链式延迟调用
面试题。
题目:
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。喜欢的掘友们可以点赞关注点个收藏~