Asynchronous Programming

Asynchronous programming is the cornerstone of responsive JavaScript applications. It allows the engine to initiate long-running operations—like network requests or file reads—and continue executing other code while waiting for the result.


1. The Evolutions: From Callbacks to Promises

I. Callbacks

The original way to handle async was by passing a function (callback) to another function.

II. Promises (ES6)

A Promise is an object representing the eventual completion (or failure) of an asynchronous operation and its resulting value.


2. The Modern Standard: Async/Await (ES2017)

Async/Await is "Syntactic Sugar" over Promises. It allows you to write asynchronous code that looks and behaves like synchronous code, making it significantly easier to read and maintain.

async function fetchData() {
    try {
        const response = await fetch("https://api.example.com/data");
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error("Failed to fetch:", error);
    }
}

3. Handling Parallelism: Promise.all

Sometimes you want to fire off multiple requests at once and wait for all of them to finish.

const [user, posts] = await Promise.all([
    fetchUser(id),
    fetchPosts(id)
]);

4. The Microtask Queue Priority

As discussed in Module 15, Promise callbacks are placed in the Microtask Queue.


Interview Pro-Tips: Error Handling in Async

If an interviewer asks how to handle errors in an async function:


Technical Summary

  1. Promise: An object-based representation of a future value.
  2. Async/Await: A way to linearize asynchronous logic.
  3. Non-Blocking: Async operations are offloaded to Web APIs (browser) or libuv (Node.js).