Consider we have multiple async tasks A, B, C, D, and E ( not promises). A, B, and C are independent tasks while D depends on A and B to perform its task while E depends on D and C to perform its task. Write a task function/class in JavaScript to solve this problem.
To solve this problem. We create a class that will take the dependencies and a callback function as input.
In the dependencies list, we will check if all the tasks in the list is completed or not, if it is completed then filter them out as we no longer need to run them.
If there are no items in dependencies, invoke the callback directly.
Otherwise, if there are dependencies pending, push them into a list, and execute them one by one. Once all are completed invoke the callback.
Use a flag to determine the state of the task, i.e completed or not.
class Task { // accept the dependencies list // and the callback constructor(dependencies = [], job) { // filter the dependencies that are not yet completed this.dependencies = dependencies ? dependencies.filter(dependency => dependency instanceof Task && !dependency.isCompleted) : []; this.currentDependencyCount = this.dependencies.length; // the callback this.job = job; // if current task is done this.isCompleted = false; // store the dependencies list callback // to execute is sequence this.subscribedList = []; // start the job this.processJob(); } processJob() { // if there is dependency // subsribe to each of them if (this.dependencies && this.dependencies.length) { for (let dependency of this.dependencies) { dependency.subscribe(this.trackDependency.bind(this)); } } // else invoke the callback directly else { this.job(this.done.bind(this)); } } // if all the dependecies are excuted // invoke the callback trackDependency() { this.currentDependencyCount--; if (this.currentDependencyCount === 0) { this.job(this.done.bind(this)); } } // push the callback to the list subscribe(cb) { this.subscribedList.push(cb); } // if the current task is done // mark it as complete // invoke all the dependecy callbacks. // to print it in sequence done() { this.isCompleted = true; for (const callback of this.subscribedList) { callback(); } } }
Input: const processA = new Task(null, (done) => { setTimeout(() => { console.log('Process A'); done(); }, 100); }); const processB = new Task([processA], (done) => { setTimeout(() => { console.log('Process B'); done(); }, 1500); }); const processC = new Task(null, (done) => { setTimeout(() => { console.log('Process C'); done(); }, 1000); }); const processD = new Task([processA, processB], (done) => { setTimeout(() => { console.log('Process D'); done(); }, 1000); }); const processE = new Task([processC, processD], (done) => { setTimeout(() => { console.log('Process E'); done(); }, 100); }); const createAllDoneInstance = (allDoneCallback) => new Task([processA, processB, processC, processD, processE], allDoneCallback); createAllDoneInstance((done) => { console.log('All is done!'); done(); }); Output: "Process A" "Process C" "Process B" "Process D" "Process E" "All is done!"