setTimeout (for request delays in code execution) that work asynchronously (concurrent thread processing) on browser web APIs. The event loop has two types of tasks: microtasks (job tasks like promises) and macrotasks (the callback queue or event queue). The job tasks inside the event loop also includes the render steps (like requestAnimationFrame(rAF), css style calculation, layout, and painting the actual pixel data). The microtask queue in the event loop handles promises and will always be prioritized before the task queue and render steps. Every loop in the event loop is one tick. The job tasks like promises are executed first. Because promises can reference promises that can reference promises, there is a variable called processMaxTick to limit job tasks to 1000 jobs. The job tasks always run first in the first tick in the event loop up to the processMaxTick limit, and then on the next tick the macrotasks including the callback queue tasks are run in the event loop.
Whenever an asynchronous function is called, it will follow instructions to send it to a browser web API. Unlike the call stack, the callback queue follows the FIFO order (First In, First Out), meaning that the calls are processed in the same order they’ve been added to the queue. As mentioned above, the event loop handIes macrotask queues, microtask queues (job tasks), and render list operations. The task queues include callback queues or event queues; in addition, web APIs can add to the task queues. In
setTimeout, when you pass in a callback function and 1000ms timer, the web API will set-up the timing operation to be calculated in a macrotask callback queue in the event loop. Eventually, the invoked callback task reaches the front of the callback macrotask queue and is picked up by the event loop and is executed in the call stack. The event loop constantly checks to see if the call stack is empty. Empty as in all of the synchronized code functions have been popped out (removed) from the call stack. Whenever the call stack is empty, the event loop will check the macrotask callback queue for any waiting messages, starting from the oldest message. Once it finds one, it will add it to the stack, which will execute the function in the message.
The callback we passed as an argument to
Three super cool JS features (callback functions, promises and async/await) allow it to run asynchronously with third party browser web APIs including XHR (via
fetch), Timer (via
setTimeout), and DOM (via
#content from the server.
A Promise is an object that handles the eventual success or eventual failure of async operations like requesting data from the
fetch XHR API. Promises were created to solve the famous callback hell problem but introduce complexities on its own, and specifically syntax complexity. Promises has three states: pending (the initial stage), resolved (
then works when a promise is resolve), or rejected (
catch works when a promise is rejected). By avoiding callback hell, promises create DRYer code than callback functions alone like
Async/await is a combination of promises and generators and the next evolution that creates even DRYer code than promises. I go more into async/await in this another blog post.
Our programs are not getting stuck when an element of our code block takes forever to load, and that’s why I love asynchronization.