admin管理员组文章数量:1414940
I was solving this interesting javascript problem (interview question) and I got stuck on how I can implement this using promises.
Problem:
Write a scheduler in JavaScript that accepts max number of concurrent tasks as a parameter and schedules tasks (each task may take arbitrary time to plete).
Please note that we need to only execute "n" (concurrent) tasks at a time before proceeding to execute other tasks.
This is my implementation:
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));
I was solving this interesting javascript problem (interview question) and I got stuck on how I can implement this using promises.
Problem:
Write a scheduler in JavaScript that accepts max number of concurrent tasks as a parameter and schedules tasks (each task may take arbitrary time to plete).
Please note that we need to only execute "n" (concurrent) tasks at a time before proceeding to execute other tasks.
This is my implementation:
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));
How can I use promises / async await to implement this? Should I wrap everything around a promise before pushing?
Can someone enlighten?
Share Improve this question edited Aug 14, 2018 at 22:50 TechnoCorner asked Aug 14, 2018 at 21:51 TechnoCornerTechnoCorner 5,17510 gold badges45 silver badges89 bronze badges 11- the problem appears odd, since almost nothing in JS actually runs "concurrently" unless it's an inherently async operation (e.g. AJAX) – Alnitak Commented Aug 14, 2018 at 21:55
- This was asked to me in one of the interview questions in top tech panies so I'm trying to solve it using Promises @Alnitak – TechnoCorner Commented Aug 14, 2018 at 21:55
- I believe in this case, the concurrency means that the user has to execute only "X" items from the queue at a time. – TechnoCorner Commented Aug 14, 2018 at 21:57
- Unless it's a queue of async operations, you can't. If you ever pass a task that's actually synchronous it'll run to the exclusion of all others. – Alnitak Commented Aug 14, 2018 at 21:59
-
They are .. please take a look at the task.. it's a
setTimeout
task() .. Correct me if i'm wrong. – TechnoCorner Commented Aug 14, 2018 at 22:01
3 Answers
Reset to default 6So if you can return a promise from your task, you can tie into the the promise's then()
to alert you when the task is finished and when you can start another.
Here's an example similar to yours with a couple changes: we don't care about the length of the queue — you only want to know how many active jobs are present. So you can increment active
when starting jobs a decrement it when jobs are done.
There are a lot of ways, I'm sure to do this, but here's the outline of one idea:
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() { // this is without promises
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();
});
本文标签: asynchronousJavaScript Scheduler implementation using promisesStack Overflow
版权声明:本文标题:asynchronous - JavaScript Scheduler implementation using promises - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745196778a2647179.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论