JavaScript Interview Preparation: Priority of callback, promise, setTimeout, and process.nextTick()

Ravi Sharma
5 min readOct 9, 2023

Welcome back to this javascript interview preparation series. In this article, we will explore the priority and execution of four commonly used methods for writing asynchronous code: callbacks, promises, setTimeout, and process.nextTick().

JavaScript Main Components

The questions related to the priority of execution can be answered by investigating the event loop. Let’s recall the main components of how asynchronous JavaScript works.

JavaScript Main Components

The call stack is a LIFO (Last In, First Out) structure that stores the execution context created during the code execution. In simple words, the execution context is created every time a function is called and the call stack executes those functions.

Web APIs is the place where the async operations (setTimeout, fetch requests, promises) with their callbacks are waiting to complete. It borrows the thread from the thread pool to complete the task in the background without blocking the main thread.

The job queue (or microtasks) is a FIFO (First In, First Out) structure that holds the callbacks of async/await, promises, process.nextTick() that are ready to be executed. For example, the resolve or reject callbacks of a fulfilled promise are enqueued in the job queue.

The task queue (or macrostasks) is a FIFO (First In, First Out) structure that holds the callbacks of async operations (timer like setInterval, setTimeout) that are ready to be executed. For example, the callback of a timed-out setTimeout() — ready to be executed — is enqueued in the task queue.

The Event loop permanently monitors whether the call stack is empty. If the call stack is empty, the event loop looks into the job queue or task queue and dequeues any callback ready to be executed into the call stack.

Micro-tasks and Macro-tasks

  • Microtasks are executed before any other tasks, which means that they have a higher priority.
  • Microtasks are typically used for short, quick tasks that need to be executed immediately.
  • Macrotasks are executed only after all microtasks have been completed, which means that they have a lower priority.
  • Macrotasks are typically used for longer, more complex tasks that can wait until all microtasks have been completed.

Priority And Order Of Execution

  1. process.nextTick(): Callbacks scheduled using process.nextTick() have the highest priority. When you use process.nextTick(), the callback is executed immediately after the current operation completes but before the event loop moves on to the next phase. This makes it a way to ensure that a function is executed at the earliest possible moment in the event loop.
  2. Promise: Promises are typically executed after process.nextTick(). However, they are prioritized over callbacks scheduled with setTimeout().
  3. setTimeout(): Callbacks scheduled with setTimeout() are placed in the timer phase of the event loop. They will be executed after the current operation, promises, and any previously scheduled setTimeout() callbacks have completed.
  4. Callback: Regular callbacks (not scheduled using process.nextTick()) have the lowest priority. They are executed after the event loop processes process.nextTick(), promises, and setTimeout() callbacks.

#1. Promise vs setTimeout()

Promise.resolve(1) is a static function that returns an immediately resolved promise. setTimeout(callback, 0) executes the callback with a delay of 0 milliseconds.

Because of the event loop priorities dequeuing jobs from the job queue(which stores the fulfilled promises callbacks) over the tasks from the task queue (which stores timed out setTimeout() callbacks).

Output

Promise first!
Timed out second!

#2. setTimeout vs setImmediate()

here priority of setImmediate() is higher than setTimeout() hence callback of setImmediate is executed first.

Output

setImmediate called
Timed out with 0 second!
Timed out with 10 second!

#3. Promise vs setTimeout() vs setImmediate() vs process.nextTick

A process.nextTick callback is added to process.nextTick queue. A Promise.then() callback is added to promises microtask queue. A setTimeout, setImmediate callback is added to macrotask queue.

A function passed to process.nextTick() is going to be executed on the current iteration of the event loop, after the current operation ends. This means it will always execute before setTimeout and setImmediate.

The event loop executes tasks in process.nextTick queue first, and then executes promises microtask queue, and then executes macrotask queue.

Output

Hello
process nextTick
Promise first!
Timed out with 0 second! // ?
setImmediate called // ?
Timed out with 10 second!

here in the output setTimeout with 0 seconds executed first then setImmediate(). Please comment if you know, then I will add my answer.

#4. Promise Constructor

we know that Synchronized code always executed sequentially from top to bottom. When we call new Promise(callback), the callback function will be executed immediately.

Output

Ravi 
promise
Sharma

#5. Promise Constructor with then() handler

here we have an asynchronous code. That is, the callback function in .then(). JavaScript engine always executes synchronous code first, then asynchronous code.

Output

Ravi 
promise callback
Sharma
promise resolved

Hope you like this article, please comment if you have any doubts.

Follow me on Medium and LinkedIn (https://www.linkedin.com/in/ravics09/)

--

--