我正在解决这个有趣的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));
我如何使用promises / async等待来实现呢?在执行之前,我应该将所有内容都包裹在一个诺言中吗?
有人可以开导吗?
答案 0 :(得分:3)
因此,如果您可以从任务中返回承诺,则可以绑定到承诺的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)
答案 1 :(得分:-1)
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();
});