DEV Community

Iszyk
Iszyk

Posted on

Asynchronous Javascript

Asynchronous JavaScript is a way of writing code that allows tasks to run without blocking the rest of your program.

In simple terms: instead of waiting for a code to finish executing like fetching data from an API, JavaScript continues executing other code and comes back to the result later.

We basically have two types of operations in javascript, synchronous and asynchronous. The primary difference is that synchronous operations occur sequentially, requiring one task to finish before the next begins, while asynchronous operations allow multiple tasks to run concurrently without waiting, improving efficiency and responsiveness. Synchronous is "blocking" (wait-for-result), while asynchronous is "non-blocking" (continue-to-other-tasks).

Example of synchronous operation;-


let data = fetchData(); // waits here until done

console.log(data);
console.log("End");
Enter fullscreen mode Exit fullscreen mode


The app pauses until fetchData() finishes.

Example of asynchronous operation;-

console.log("Start");

fetchData().then(data => {
  console.log(data);
});

console.log("End");
Enter fullscreen mode Exit fullscreen mode


plaintext
The Output;-

Start
End
(data comes later)
Enter fullscreen mode Exit fullscreen mode


plaintext

🔹 Common Asynchronous Techniques

  1. Callbacks

A callback is a function passed as an argument to another function, which is then executed (or "called back") inside that outer function to complete a specific task, because functions in JavaScript are First-class Objects, they can be treated like any other variable and passed between functions.
For example,

A Simple Synchronous Callback

function greet(name, callback) {
  console.log("Hello, " + name);
  callback(); // Executing the callback function
}

function sayGoodbye() {
  console.log("Goodbye!");
}

// Pass 'sayGoodbye' as a callback to 'greet'
greet("Alice", sayGoodbye);
Enter fullscreen mode Exit fullscreen mode


plaintext

In this example, the greet function takes a callback as a parameter and executes it immediately after performing its own logic.

Asynchronous Callback
Callbacks are essential for asynchronous programming, where a task needs time to complete (like a timer or data fetch) without blocking the rest of the code.

console.log("Start");

// setTimeout takes an anonymous function as a callback
setTimeout(() => {
  console.log("This appears after 2 seconds");
}, 2000);

console.log("End");
Enter fullscreen mode Exit fullscreen mode


plaintext

  1. Promises

In JavaScript, a Promise is an object representing the eventual completion or failure of an asynchronous operation and its resulting value. It serves as a placeholder for a result that is not yet available, allowing you to handle asynchronous code in a cleaner way than traditional callbacks.
Promises exist in one of three states: pending (ongoing), fulfilled (successful), or rejected (failed). Once fulfilled or rejected, a promise is settled and cannot change state.

You create a Promise using the new Promise() constructor, which takes an executor function. This function runs immediately and receives two callback arguments provided by the JavaScript engine: resolve and reject.

const myPromise = new Promise((resolve, reject) => {
  const success = true; 
  if (success) {
    resolve("Operation Successful!"); // Moves state to Fulfilled
  } else {
    reject("Operation Failed.");      // Moves state to Rejected
  }
});
Enter fullscreen mode Exit fullscreen mode


plaintext
To handle the result of a Promise, you attach handlers using these methods:
.then(): Runs when the promise is fulfilled. It can also take a second argument for rejection.
.catch(): A shorthand for handling errors. It runs if the promise is rejected at any point in the chain.
.finally(): Runs after the promise settles, regardless of whether it succeeded or failed. It is often used for cleanup.

const myPromise = new Promise((resolve, reject) => {
  const success = true; 
  if (success) {
    resolve("Operation successful!"); // Marks as fulfilled
  } else {
    reject("Something went wrong.");  // Marks as rejected
  }
});

// Consuming the promise
myPromise
  .then((data) => console.log(data))    // Runs if resolved
  .catch((err) => console.error(err))   // Runs if rejected
  .finally(() => console.log("Done"));  // Always runs

Enter fullscreen mode Exit fullscreen mode


plaintext

  1. Async/Await (Modern & Cleaner)

In JavaScript, async and await are keywords used to write asynchronous code that looks and behaves like synchronous code. They are "syntactic sugar" built on top of JavaScript Promises, making complex asynchronous flows easier to read and maintain.

The Concept

async Keyword: Placed before a function declaration to define an asynchronous function.
An async function always returns a Promise.
If the function returns a value, that value is automatically wrapped in a resolved Promise.

await Keyword: Can only be used inside an async function (or at the top level of a module).
It pauses the execution of the async function until the Promise settles (resolves or rejects).
Once the Promise resolves, it returns the result. If it rejects, it throws an error.
While the function is paused, the JavaScript engine can perform other tasks, making it non-blocking.

async function fetchData() {
  try {
    // Execution pauses here until the fetch promise resolves
    const response = await fetch('https://example.com');

    // Execution pauses again for the .json() promise
    const data = await response.json();

    console.log(data);
  } catch (error) {
    // Standard try/catch handles any errors in the async flow
    console.error("Fetch error:", error);
  }
}

fetchData();
Enter fullscreen mode Exit fullscreen mode

To fetch data from an API using the Fetch API, the async/await pattern is commonly used.

Top comments (1)

Collapse
 
oluwatrillions profile image
Toby

I love how simply explanatory it is. Thank you