这两天面试,遇到一道有趣的手写题,其实一开始挺懵逼的,因为是网页写代码,也不好调试,到最后也就完成了大概,还有剩下的缓存任务 和当只有一个job的判断没完成就自动交卷了。
题目如下
实现一个Scheduler,并发限制2个任务运行,
js
class Scheduler {
constructor() {}
add(task) {
}
}
/* 测试代码,请勿修改 */
const timeout = (time) =>
new Promise((resolve) => {
setTimeout(resolve, time);
});
const scheduler = new Scheduler();
const addTask = (time, order) => {
scheduler.add(() => timeout(time)).then(() => console.log(order));
};
addTask(1000, '1');
addTask(500, '2');
addTask(300, '3');
addTask(400, '4');
// output: 2 3 1 4
// 一开始,1、2两个任务进入队列
// 500ms时,2完成,输出2,任务3进队
// 800ms时,3完成,输出3,任务4进队
// 1000ms时,1完成,输出1
// 1200ms时,4完成,输出4
参考答案
js
class Scheduler {
jobArray = [];
runJobsArray = [];
freshing = false;
isFrshing = false;
seenJobArray = [];
constructor() {}
runJobs() {
if (this.runJobsArray.length < 2) {
const currentJob = this.jobArray.shift();
if (currentJob != null) {
this.runJobsArray.push(currentJob);
} else if (currentJob == null) {
const j = this.runJobsArray[0];
const senndJobObj = this.seenJobArray.find((s) => s.j === j);
if (senndJobObj) {
senndJobObj.promise.then((res) => {
j.resolve(res);
});
}
}
}
if (this.runJobsArray.length === 2 && !this.isFrshing) {
this.isFrshing = true;
Promise.race(
this.runJobsArray.map((j) => {
const senndJobObj = this.seenJobArray.find((s) => s.j === j);
if (senndJobObj) {
return senndJobObj.promise.then((res) => {
return {
res,
resolve: j.resolve,
};
});
}
const promise = j.task();
if (senndJobObj == null) {
this.seenJobArray.push({ j, promise });
}
return promise.then((res) => {
return {
res,
resolve: j.resolve,
};
});
})
).then((res) => {
res.resolve(res);
this.isFrshing = false;
this.runJobsArray = this.runJobsArray.filter(
(r) => r.resolve !== res.resolve
);
this.runJobs();
});
}
}
add(task) {
let resolveValue;
const promise = new Promise((resolve) => {
resolveValue = resolve;
});
this.jobArray.push({ task, resolve: resolveValue });
this.runJobs();
return promise;
}
}
/* 测试代码,请勿修改 */
const timeout = (time) =>
new Promise((resolve) => {
// console.log('执行了', time);
setTimeout(resolve, time);
});
const scheduler = new Scheduler();
const addTask = (time, order) => {
scheduler.add(() => timeout(time)).then(() => console.log(order));
};
addTask(1000, '1');
addTask(500, '2');
addTask(300, '3');
addTask(400, '4');
// 输出
// output: 2 3 1 4
// 一开始,1、2两个任务进入队列
// 500ms时,2完成,输出2,任务3进队
// 800ms时,3完成,输出3,任务4进队
// 1000ms时,1完成,输出1
// 1200ms时,4完成,输出4