(面试题)JS实现一个任务队列
这是一道 cvte 的面试题,我当时没有做出来,所以想记录下来,一方面是为了总结思考问题的方法,另一方面便于日后回顾。
题目
要求:根据题目描述及输出结果补全 queue 方法。
function fun1(cb) {
setTimeout(() => {
console.log('1');
cb();
}, 300);
}
function fun2(cb) {
setTimeout(() => {
console.log('2');
cb();
}, 250);
}
function fun3(cb) {
setTimeout(() => {
console.log('3');
cb();
}, 150);
}
function queue(list, count) {
}
queue([fun1, fun2, fun3], 2); // 依次输出 2、1、3
说明
fun1、fun2、fun3表示三个待执行的任务,参数:
- cb: 回调函数
queue为执行任务的方法,参数:
- list: 待执行任务数组
- count: 可同时执行的最大任务数
简单来说,比如在银行办理业务,当前有 2 个窗口,有 3 个人需要办理业务,但是窗口只能容纳两个人,所以需要排队叫号。当某个窗口的人业务办理完毕以后,下一个人就到这个窗口办理业务。
分析
过程
queue 方法执行后,fun1 和 fun2 同时开始执行,fun2 先执行完,接着 fun3 开始执行。
思路
每个方法执行完后,会执行回调函数 cb,有什么用呢?
表明当前任务执行完毕。
那么,当前任务执行完毕后,应该做什么呢?
找到下一个该执行的任务。
理清楚上面这些思路,就成功了一半了。既然回调函数的执行表示当前任务执行完毕,那么,我们就应该在回调函数中找到下一个该执行的任务。
所以,我们的目的主要在于如何编写回调函数。
实现
function queue(list, count) {
function next() { }
for(let i = 0; i < count; i++) {
list[i](next);
}
}
实现到上面这一步很容易,我们将任务按照最大窗口数 count 同时执行。现在,我们要想办法找到下一个该执行的任务。
我们如何知道当前执行的任务是哪一个呢?下标。
那么找到下一个任务就很容易了,那就是下一个下标。
function queue(list, count) {
// 注意 1
let index = count;
function next() {
// 注意 2
list[index] && list[index++](next);
}
for(let i = 0; i < count; i++) {
list[i](next);
}
}
上面这段代码需要注意的地方有两点:
index的值取count的原因,一开始会执行count个任务,所以下一个任务下标直接从count开始。- 在这里要判断数组越界,当
list[index]为有效值时再执行该函数。
总结
碰到这个问题时,我第一时间没有理清思路,根本没有考虑到回调函数的作用,所以没有写出来。思考问题时,要考虑到问题的核心是什么,目的是什么,这样才能思路清晰、事半功倍。