Julien
Julien

Reputation: 11

Are "Event Loop" and "Event Queue" the same in JavaScript?

I am new to JavaScript and want to know how "JS" handles Asynchronous Operations. I came to know that it does it with the help of "Event Loop" and "Event Queue" but I don't know the difference. Can someone help me out.

An example of asynchronous operations can be:

function alpha(){
  setTimeout(() => alert("hi"), 3000);
};

alpha();

Upvotes: 1

Views: 1274

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074285

The event loop is the loop that the browser (or other JavaScript host) runs picking up the top item from the event queue (more generally a job or task queue, the queue listing the events/jobs/tasks that are waiting to be processed) and processing it, then going back for the next one and processing it, etc.

In pseudocode terms (and leaving out lots of details):

// Event/job/task loop:
while (running) {
    const task = taskQueue.pop();
    if (task) {
        task();
    }
}

JavaScript code or host environment events might add jobs/tasks to the queue, to be picked up by the loop when it gets to them.

The HTML specification goes into some detail about the process here. At first glance it may seem odd to have that information in the HTML specification, but that specification describes not only HTML (the markup language), but also how user agents (including browsers) should handle processing/presenting web pages.

The JavaScript specification talks about this here although it doesn't go into detail about what kind of loop the host should perform, since that's host-specific.

As an example of a non-browser JavaScript host, the Node.js documentation describes its loop here.


One of the more important details left out of the pseudocode above is that there are at least two queues in nearly all JavaScript hosts: The main one (called the "task queue" by the HTML specification) and the one used for promise reactions and optionally other things (called the "microtask queue" by the HTML specification). So that job loop really looks more like:

// Event/job/task loop:
while (running) {
    const task = taskQueue.pop();
    if (task) {
        task();
        // Microtask loop:
        while (!microtaskQueue.isEmpty()) {
            const microtask = microtaskQueue.pop();
            microtask();
        }
    }
}

Note how the microtask queue is emptied after every task, which means that if the task queue has Task 1, Task 2, and Task 3 in it, and during the processing of Task 1 two microtasks are added to the microtask queue, those microtasks get run at the end of Task 1, before Task 2. Here's an example: setTimeout queues tasks, but promise reactions (calling fulfillment or rejection handlers) are microtasks:

// Task 1
console.log("Queuing Task 1");
setTimeout(() => {
    console.log("Task 1 - start");
    // Note: The promise handling below is atypical, tailored specifically to
    // this example. Normally you chain promises, and you handle rejections.
    // Note that the below says we're "queuing Microtask X" because we know
    // that the promise is already fulfilled. Normally, when you call `then`,
    // you *don't* know whether the promise is fulfilled yet, so the microtask
    // may be added when you call `then`, or may be added later when the
    // promise is fulfilled
    const p = Promise.resolve();
    console.log("Task 1 queuing Microtask A");
    p.then(() => {
        console.log("Microtask A");
    });
    console.log("Task 1 queuing Microtask B");
    p.then(() => {
        console.log("Microtask B");
    });
    console.log("Task 1 - end");
}, 0);

// Task 2
console.log("Queuing Task 2");
setTimeout(() => {
    console.log("Task 2");
}, 0);

// Task 3
console.log("Queuing Task 3");
setTimeout(() => {
    console.log("Task 3");
}, 0);
.as-console-wrapper {
    max-height: 100% !important;
}

Upvotes: 7

Related Questions