Ways to make Javascript code Asynchronous

Before going deep into the core of the JavaScript runtime and how async code tasks are run behind the scenes, let’s get the basics clear. JavaScript is a single-threaded language. This means it has only one call stack and one memory heap. Hence, it can only execute one code at a time. In other words, the code is executed in an orderly fashion. It must execute one code in the call stack before moving to the next code to be executed. There are two types of code tasks in JavaScript, asynchronous code which runs and gets executed after certain loading, and synchronous, which gets executed instantaneously. Let us understand the difference between the synchronous and asynchronous code before moving further.

Synchronous code:

  • Most of the code is synchronous.

  • It is executed in a line-by-line fashion, i.e., each line of code waits before the previous line to finish its execution.

  • Long-running code operations block the code execution for further stacked code executions.

Asynchronous code:

  • Asynchronous code isn’t synchronous. I.e., the code is executed after a task that runs in the background finishes.

  • It is non-blocking in nature. Execution doesn’t wait for an asynchronous task to finish its work.

  • Callback functions alone don’t make the code asynchronous.

JavaScript code can be made asynchronous using various techniques. Asynchronous programming allows tasks to be executed concurrently without blocking the execution of other tasks. Here are some common ways to achieve asynchronicity in JavaScript, along with examples:

1.Callback Function

Callbacks are functions passed as arguments to other functions and executed later, typically after an asynchronous operation completes.

function fetch(callback) {
  setTimeout(() => {
    callback("Data fetched successfully");
  }, 5000);
}

console.log("Fetching data...");
fetchData((data) => {
  console.log(data);
});
console.log("Data fetching in progress...");

2.Promises:

Promises provide a more structured and easier-to-read way of handling asynchronous operations.

function getData() {
  let promise = new Promise((resolve, reject) => {
    let connection = true
    if (connection) {
      resolve ({name: "john doe"})
    }else {
      reject ("connection failure")
    }
  })
  console.log("hello");
  return promise
}
getData().then((result) => {
  console.log(result);
}).catch((err) => {
  console.log(err);
});
getData.signal = "OK"
console.log(getData.signal);

// Output
// hello
// OK
// { name: 'john doe' }

3.Async/Await:

Async/await is syntactic sugar built on top of promises, providing a more synchronous-like way of writing asynchronous code.

function fetchData() {
  let p = new Promise((resolve, reject) => {
    let connection = true
    if (connection) {
      resolve ({name: "john doe"})
    }else {
      reject ("connection failure")
    }
  })
  console.log("hello");
  return p
}

async function getResult () {
  let res = await fetchData()
  console.log(res);
}
getResult()
getResult.signal = "OK"
console.log(getResult.signal);

// output
// hello
// OK
// { name: 'john doe' }