昨天面试的时候遇到了这两个函数编程题,但是该死的是完全没有思路(悲伤)
-
利用 Promise 完成一个队列,队列中的任务数满了的话,后续任务不执行,当队列中的任务有完成的状态,才会添加新的任务进入队列
-
完成一个 retry 函数,传入一个执行函数和一个计数器,在一定次数范围内,如果函数执行失败的话会再次尝试执行该函数,直到执行成功
面试结束之后,我上网上搜索了一下类似的问题,接下来是我总结之后的思路,以及最后成功的代码
Promise 队列
这个问题有以下几个重点
- 队列: 存放未执行的任务队列
- 计数器: 存放当前正在执行的任务数量
- 任务执行最大数量
- 添加任务函数
- 执行任务函数
接下根据我们上述描述的重点来创建一个任务队列执行类
class Scheduler {
// 初始化任务队列,以及根据传入的数量来限制最大执行数量
constructor(maxCount) {
this.maxCount = count
this.list = []
this.count = 0
}
add() {
}
start() {
}
}
接下我们就要来编写添加函数了,在写添加函数之前我们首先思考一下这个添加函数里面应该注意那些东西
首先,如果我们想要在任务执行完成之后对执行结果操作的话,这个 add 函数必须返回一个 promise 函数
add(task) {
return new Promise(resolve => {
resolve()
})
}
添加一个任务的时候,我们需要把这个任务添加到未执行的任务队列的存放起来
add(task) {
return new Promise(resolve => {
resolve(() => {
this.list.push(task())
})
})
}
这个时候就出现了一个问题,我们应该怎样监控这个任务是否已经执行完成,这个时候 promise 的作用就来了,我们在 then
中就可以判断到函数是否执行成功
add(task) {
return new Promise(resolve => {
resolve(() => {
this.list.push(Promise.resolve(task()).then())
// 如果 task 执行之后的返回值是一个promise对象则可以修改成以下形式
// this.list.push(task().then())
})
})
}
添加函数先写到这里,然后我们来写执行函数,在start函数中我们需要做的就是判断一下正在执行任务数是否小于最大执行数,然后从待执行队列中取出一个任务并执行,然后将正在执行的任务数加上1
start() {
if(this.count < this.maxCount) {
this.count++
this.list[0] && this.list.shift()()
}
}
接下来修改 add 函数 为当我们添加一个任务时,在最后执行一下执行函数,在执行任务完成之后,减少执行队列数,并触发执行函数,最后把任务的返回值 return
出来
add(task) {
return new Promise(resolve => {
this.list.push(() => {
resolve(Promise.resolve(task()).then(s => {
this.count--
this.start()
return s
}))
})
this.start()
})
}
接下来实例化任务队列,并创建一个异步执行方法和一个添加任务函数
let scheduler = new Scheduler(5)
let timeout = (time) => {
return new Promise(resolve => {
setTimeout(resolve, time)
})
}
let addTask = function addTask(time, order) {
scheduler.add(() => timeout(time)).then(() => {
console.log(time, order)
})
}
附上完整代码
class Scheduler {
constructor(count) {
this.list = []
this.maxCount = count
this.count = 0
}
add(task) {
return new Promise(resolve => {
this.list.push(() => {
resolve(Promise.resolve(task()).then(s => {
this.count--
this.start()
return s
}))
})
this.start()
})
}
start() {
console.log(this.count)
if(this.count < this.maxCount) {
this.count++
this.list[0] && this.list[0]()
this.list.shift()
}
}
}
let scheduler = new Scheduler(5)
let timeout = (time) => {
return new Promise(resolve => {
setTimeout(resolve, time)
})
}
let addTask = function addTask(time, order) {
scheduler.add(() => timeout(time)).then(() => {
console.log(time, order)
})
}
addTask(5000,'1')
addTask(1100,'2')
addTask(2200,'3')
addTask(3300,'4')
addTask(3300,'5')
addTask(3300,'6')
addTask(3300,'7')
addTask(2200,'8')
retry 函数
function retry(fun, count) {
if(count === 0) return
let val = fun()
if(val > 3) {
return val
} else {
return retry(fun, --count)
}
}
function random() {
return Math.random() * 5
}
console.log(retry(random, 5))
这个问题现在看起来挺简单的,但是当时估计相差了,思路都理解错了,难受
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!