JavaScript Fundamentals: Asynchronous Logic

What is asynchronous logic in JavaScript? How does asynchronous logic work? What are the ways of writing asynchronous logic in JavaScript?

JavaScript Fundamentals: Asynchronous Logic
JavaScript Fundamentals: Asynchronous Logic

Asynchronous logic is a form of programming that allows for tasks to be completed out of order. This can be helpful when dealing with tasks that take a long time to complete, such as making an HTTP request or waiting for a user to input data.

Requests are asynchronous because they do not block the execution of code. This means that code can continue to run while the request is being processed.

A blocking language is a programming language where the program cannot continue until a certain task is completed. A non-blocking language is a programming language where the program can continue before a certain task is completed. JavaScript is a non-blocking language.

In asynchronous programming, there are two ways to structure your code:

  1. Callbacks
  2. Promises

Asynchronous logic with callbacks

Callbacks are the simplest way to structure your code. You simply pass a callback function as an argument to another function. The callback function will then be executed at some point in the future.

Promises are a more advanced way to structure your code. With promises, you can chain together multiple asynchronous tasks and make sure that they all run in the correct order.

Here is an example of asynchronous code using callbacks:

function makeRequest(url, callback) {
  // make the request
  callback(response);
}

makeRequest('http://www.example.com', function(response) {
  // do something with the response
});

And here is an example of asynchronous code using promises:

function makeRequest(url) {
  // make the request
  return promise;
}

makeRequest('http://www.example.com').then(function(response) {
  // do something with the response
});

Asynchronous logic with promises

A promise is an object that represents the result of an asynchronous operation. A promise can be in one of three states: pending, fulfilled, or rejected.

A pending promise represents an asynchronous operation that has not yet completed. A promise is considered fulfilled when the asynchronous operation has completed successfully. A promise is considered rejected when the asynchronous operation has failed.

Writing a promise in JavaScript

A promise is a JavaScript object that represents the eventual completion (or failure) of an asynchronous operation, and its resulting value. Promises provide a simpler alternative for executing, composing, and managing asynchronous operations when compared to callback-based approaches.

A promise is a JavaScript object that represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.

A promise can be in one of three states:

  • pending: initial state, not fulfilled or rejected.
  • fulfilled: successful operation, the promise has a value.
  • rejected: failed operation, the promise has a reason for the failure.

A promise can be created using the Promise constructor:

const promise = new Promise((resolve, reject) => {
  // do a thing, possibly async, then…

  if (/* everything turned out fine */) {
    resolve("Stuff worked!");
  }
  else {
    reject(Error("It broke"));
  }
});

The promise constructor takes a function as an argument, this function takes two arguments: resolve and reject. The resolve and reject functions are called when the promise is either fulfilled or rejected.

If the asynchronous operation succeeds, call the resolve function with the successful value: resolve(value);

If the asynchronous operation fails, call the reject function with the reason for the failure: reject(reason);

Once a promise is fulfilled or rejected, it is immutable (i.e. it can never change again).

Writing a promise chain in JavaScript

Chaining is a method of combining multiple promises into a single promise. By doing this, you can create complex asynchronous workflows.

A promise chain is a sequence of Promises that are chained together. The first Promise in the chain is created inside of an executor function, and the subsequent Promises are created within the .then() handlers of the previous Promises.

The result of a promise chain is the same as the result of calling .then() on a Promise: the resolved value of the final Promise in the chain.

The following is a simple promise chain that resolves to the string "Hello, world!":

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('Hello');
    }, 1000);
});

const promise2 = promise1.then((result) => {
    return result + ', world!';
});

promise2.then((result) => {
    console.log(result); // "Hello, world!"
});


Asynchronous logic is a powerful tool that can help improve the performance of your web applications. When used correctly, it can help you avoid costly delays and make your code more responsive. However, asynchronous logic can also be confusing and error-prone. Be sure to carefully consider your application's needs before adding asynchronous logic to your code.

💡
Want to check out my other stuff? See my link wall at Zipply.io.