使用 promise 实现 JavaScript 调度程序



我正在解决这个有趣的javascript问题(面试问题(,我陷入了如何使用promises实现这一点的困境。

问题:

用 JavaScript 编写一个接受最大并发数的调度程序 任务作为参数并计划任务(每个任务可能需要任意 完成时间(。

请注意,在继续执行其他任务之前,我们一次只需要执行"n"(并发(任务。

这是我的实现:

var exampleTaskA = function () {
setTimeout(function () {
console.log('Task A Done');
}, 1000);
};
function TaskRunner(concurrency) {
this.limit = concurrency;
this.store = [];
this.len = this.store.length;
}
TaskRunner.prototype.push = function (task) {
this.store.push(task);
function getWorker(store, limit) {
if(!store.length) return;
if(store.length <= limit) {
const cur = store.shift();
if(cur) cur();
getWorker(store, limit);
}
}
getWorker(this.store, this.limit);
}
var task = new TaskRunner(2);
console.log(task.push(exampleTaskA));
console.log(task.push(exampleTaskA));
console.log(task.push(exampleTaskA)); 
console.log(task.push(exampleTaskA));
console.log(task.push(exampleTaskA));
console.log(task.push(exampleTaskA));
console.log(task.push(exampleTaskA));

如何使用承诺/异步等待来实现这一点?在推动之前,我应该把所有事情都包裹在承诺上吗?

有人可以开导吗?

因此,如果您可以从任务中返回承诺,则可以绑定到承诺的then()中,以便在任务完成以及何时可以开始另一个任务时提醒您。

下面是一个类似于您的示例,但进行了一些更改:我们不关心队列的长度 - 您只想知道存在多少活动作业。因此,您可以在启动作业时递增active,在作业完成时递减。

有很多方法,我肯定会这样做,但这里有一个想法的大纲:

const exampleTaskA = (name) => new Promise(resolve => setTimeout(function() {
console.log(`Task ${name} Done`);
resolve()
}, Math.floor(Math.random() * 2000)))
function TaskRunner(concurrency) {
this.limit = concurrency;
this.store = [];
this.active = 0;
}
TaskRunner.prototype.next = function() {
if (this.store.length) this.runTask(...this.store.shift())
}
TaskRunner.prototype.runTask = function(task, name) {
this.active++
console.log(`Scheduling task ${name} current active: ${this.active}`)
task(name).then(() => {
this.active--
console.log(`Task ${name} returned, current active: ${this.active}`)
this.next()
})
}
TaskRunner.prototype.push = function(task, name) {
if (this.active < this.limit) this.runTask(task, name)
else {
console.log(`queuing task ${name}`)
this.store.push([task, name])
}
}
var task = new TaskRunner(2);
task.push(exampleTaskA, 1)
task.push(exampleTaskA, 2)
task.push(exampleTaskA, 3)
task.push(exampleTaskA, 4)
task.push(exampleTaskA, 5)
task.push(exampleTaskA, 6)
task.push(exampleTaskA, 7)

class TaskScheduler {
constructor(concurrency) {
this.limit = concurrency;
this.active = 0;
this.pool = [];
}
push(task) {
this.pool.push(task);
if (this.active < this.limit) {
this.active += 1;
this.execute(this.pool.shift());
}
}
execute(task) {
task().then(val => {
console.log(`${val} executed`);
this.active -= 1
if (this.pool.length && this.active < this.limit) {
this.execute(this.pool.shift());
}
});
}
}
const task = () => new Promise((res, rej) => setTimeout(() => res('task'), 4000));
const task2 = () => new Promise((res, rej) => setTimeout(() => res('task'), 200));
const scheduler = new TaskScheduler(2);
scheduler.push(task);
scheduler.push(task2);
scheduler.push(task2);
scheduler.push(task2);
scheduler.push(task);
scheduler.push(task);
scheduler.push(task);
scheduler.push(task);

window.addEventListener("load", function(( { 这是没有承诺的

function Task(name) {
this.isDone = false;
this.name = name;
}
Task.prototype.run = function() {
setTimeout(()=>{
this.isDone = true;
}, 3000);
}
function TaskScheduler(limit) {
this.limit = limit;
this.active = 0;
this.pendingTasks = [];
this.runningTasks = [];
}
TaskScheduler.prototype.runTask = function(task) {
this.active++;
task.run();
}
TaskScheduler.prototype.init = function() {
var interval = setInterval(() => {
// check and clean running tasks
this.runningTasks = this.runningTasks.filter((task) => {
if (task.isDone) {
this.active--;
}
return !task.isDone;
});
while(this.pendingTasks.length) {
if (this.active < this.limit) {
var task = this.pendingTasks.pop();
this.runTask(task);
this.runningTasks.push(task);
} else {
break;
}
}
if (!this.pendingTasks.length) {
clearInterval(interval);
}
}, 0);
}
TaskScheduler.prototype.push = function(task) {
this.pendingTasks.push(task);
}
var taskSecheduler = new TaskScheduler(2);
taskSecheduler.push(new Task(1));
taskSecheduler.push(new Task(2));
taskSecheduler.push(new Task(3));
taskSecheduler.push(new Task(4));
taskSecheduler.push(new Task(5));
taskSecheduler.push(new Task(6));
taskSecheduler.init();

}(;

最新更新