让我们考虑我们需要在JavaScript中创建AYNC任务跑步者,并具有以下约束:
- 任务跑步者应具有一组将被推到它的任务,
- 这些任务中的每一个都将是一些异步操作,
- 任务跑步者还应确保在单个时间点只能执行一个给定数量的任务,而其他任务则不断等待,除非他们的任务出现。
让我们首先编码解决方案
class Runner{
constructor(concurrency=1){
this.concurrency = concurrency;
this.waitList = [];
this.count = 0;
this.currentQ = [];
}
push(task){
this.waitList.push(task);
this.run();
}
run(){
let current = this;
if(this.count<this.concurrency){
this.count++;
if(this.waitLength>0){
let task = this.waitList.shift();
let id = task.id;
this.currentQueue.push(id);
this.showRunningTasks();
let done = function(){
this.currentQueue.splice(this.currentQueue.indexOf(id),1);
this.showRunningTasks();
this.count = this.count - 1;
this.run();
}.bind(current);
task.task(done);
}
}
}
showRunningTasks(){
let existingQueue = this.currentQueue.join(", ");
document.getElementId("running").innerHTML = existingQueue;
}
}
让我们逐行理解这条代码。
-
最初,我们通过
concurrency
flag,指示可以同时运行多少个任务。waitList
用于制作任务的等待列表,除非称为currentQueue
的队列为空,否则该任务将等待。初始化了count
变量以计算并发任务的数量。 -
push
方法用于将任务推向waitList
,然后我们执行运行方法。这仅表示如果队列为空,则需要运行任务 -
运行方法很有趣。首先,它通过表示为
let current = this
的第一行保留任务的上下文
-
接下来,我们检查并发性,如果候补名单有元素,我们简单地,
- 将任务ID推到Currentqueue,
- 通过方法
showRunningTasks
显示当前运行任务, - 在内部
done
method中,将被视为回调 在任务中,我们简单地从当前的ID中删除任务
队列,减少计数以减少并发任务的总数, - 最后,我们递归调用Run()方法以运行 当前功能。请注意,这里的上下文保持不变。
- 最后,我们将此功能绑定到当前上下文。
- 我们将此函数传递给任务.task函数。
现在让我们看看如何使用此方法
使用以下代码段查看结果。
let runner = new Runner(3);
let task1 = {
id: 1,
task: function(done) {
setTimeout(function() {
console.log("Task 1");
done();
}, 3000)
}
}
let task2 = {
id: 2,
task: function(done) {
setTimeout(function() {
console.log("Task 2");
done();
}, 5000)
}
}
let task3 = {
id: 3,
task: function(done) {
setTimeout(function() {
console.log("Task 3");
done();
}, 4000)
}
}
let task4 = {
id: 4,
task: function(done) {
setTimeout(function() {
console.log("Task 4");
done();
}, 9000)
}
}
runner.push(task1);
runner.push(task2);
runner.push(task3);
runner.push(task4);
您将在屏幕上看到结果1,任务3,任务2,任务4 ,这是可以预期的。