# How I Solved Preemptive Priority Task Scheduler in JavaScript

When I first saw this problem, it looked like something straight out of an Operating System.

But implementing it in JavaScript?  
That’s where things get interesting.

* * *

### What is Preemptive Scheduling?

Preemptive scheduling is an OS technique where:

A **high-priority task can interrupt** a currently running low-priority task  
CPU automatically switches execution

In simple words:

> “Important work gets preference immediately.”

* * *

**But here’s the catch in JavaScript**

JavaScript does **NOT support true preemption**

**What is “true preemption”?**

*   A running task can be forcefully stopped anytime
    
*   CPU takes control and switches tasks
    

This happens in Operating Systems

**In JavaScript**

*   If a function starts running…
    
*   Nothing can stop it until it finishes
    

That means:

> We cannot interrupt execution midway

* * *

### So how do we solve this?

Since JavaScript cannot interrupt a running task, we design tasks in such a way that they **pause themselves after some work** and give control back to the scheduler.

This allows the system to check if any higher-priority task has arrived before continuing.

We achieve this using:

*   `setTimeout`
    
*   `await` (async tasks)
    

* * *

### Problem Statement

We need to:

*   Execute tasks based on **priority**
    
*   Higher priority runs first
    
*   Allow **new high-priority tasks** to jump ahead
    
*   Since no true preemption → tasks must **yield control**
    

* * *

### My Approach

I built a `Scheduler` class with:

1.  **Priority Queue** → to store tasks
    
2.  **Sorting mechanism** → highest priority first
    
3.  **Execution loop** → runs tasks one by one
    
4.  **Yield mechanism** → allows re-evaluation after each task
    

* * *

### Implementation

```javascript
class Scheduler {
  constructor() {
    this.queue = [];
    this.timer = null;
    this.running = false;
  }

  schedule(task, priority = 0) {
    this.queue.push({ task, priority });

    // maintain priority order
    this.queue.sort((a, b) => b.priority - a.priority);

    // start scheduler only if not already running
    if (!this.running) {
      this.running = true;
      // Don’t continue immediately
      // Pause here and come back later
      this.timer = setTimeout(() => this.run(), 0);
    }
  }

  run(onAllFinished) {
    if (this.queue.length === 0) {
      this.running = false;
      this.timer = null;
      return onAllFinished && onAllFinished(null);
    }

    const { task } = this.queue.shift();

    task((err) => {
      if (err) {
        this.running = false;
        this.timer = null;
        return onAllFinished && onAllFinished(err);
      }

      // schedule next task instead of running immediately
      this.timer = setTimeout(() => this.run(onAllFinished), 0);
    });
  }
}

const scheduler = new Scheduler();
const results = [];

const createTask = (val) => (cb) => {
  results.push(val);
  cb(null);
};

scheduler.schedule(createTask("low"), 0);
scheduler.schedule(createTask("high"), 10);
scheduler.schedule(createTask("medium"), 5);

scheduler.run((err) => {
  console.log(results);
});
```

### What’s Actually Happening Behind the Scenes?

Let’s understand the key idea:

**1\. Tasks are sorted by priority**

```javascript
this.queue.sort((a, b) => b.priority - a.priority);
```

Highest priority always comes first

**2\. Only ONE task runs at a time**

```javascript
const { task } = this.queue.shift();
```

This keeps execution controlled

**3\. After every task → we pause**

```javascript
setTimeout(() => this.run(), 0);
```

This is the most important design decision

Instead of running tasks continuously:

*   We **stop after each task**
    
*   Give control back to JavaScript runtime
    
*   Then resume later
    

### **Why this works like preemption**

Let’s say:

1.  A low-priority task runs
    
2.  Before next execution, a **high-priority task is added**
    

Because we paused:

*   Scheduler gets a chance to **re-check the queue**
    
*   High-priority task moves to the top
    
*   It runs next
    

* * *

## Final Thought

This problem is not about `setTimeout`.

It’s about:

*   Understanding **how JavaScript execution works**
    
*   Designing systems within its limitations
