Asynchronous programming is a staple in software development. It’s hard to believe that this programming concept has only been around since the twenty-first century. The F# programming language was the first among its peers to introduce asynchronous programming, in 2007.

Other languages such as C#, Python, JavaScript, and C++ gradually added support for asynchronous programming. The big question is, what value does asynchronous programming add to your applications?

This article answers that and other questions, so you’ll find out all about how to use asynchronous programming.

What Is Synchronous Programming?

Synchronous programming refers to a program in its most basic form. This programming model processes the lines of code in a program or script sequentially. It always starts from the first line of code in a program. Then it waits until each line of code has completed its execution before moving on to the next.

The synchronous model also includes conditional code, such as if and while statements. Although only some code in a conditional statement will execute, the program will still run sequentially.

Synchronous Program Example

        const SyncCode = () => {
    console.log("This is the first line in the program")
    console.log("This is the second line in the program")
    console.log("This is the final line in the program")
}
 
SyncCode();

Running the JavaScript program above will produce the following output in the console:

        This is the first line in the program
This is the second line in the program
This is the final line in the program

The output above is exactly what you should expect. The program starts from the top and waits until one line of code finishes before moving to the next.

What Is Asynchronous Programming?

Asynchronous programming is the opposite of synchronous programming. The asynchronous programming model processes several lines of codes simultaneously. It doesn’t wait until the previous line of code in a program has completed its execution before moving to the next.

Related: Synchronous vs. Asynchronous Programming: How Are They Different?

Asynchronous programming can cut execution time in half, effectively creating faster computers.

Asynchronous Program Example

        const AsyncCode = () => {
    console.log("This is the first line in the program")
 
    setTimeout(() => {
        console.log("This is the second line in the program")
    }, 3000)
 
    console.log("This is the final line in the program")
}
 
AsyncCode();

Executing the JavaScript Code above will produce the following output in your console:

        This is the first line in the program
This is the final line in the program
This is the second line in the program

If you compare the console output above to the asynchronous program that generates it, you’ll see that there’s an obvious discrepancy. The call to log that says “This is the second line in the program” occurs before the one that says “This is the final line in the program”. However, the console output doesn’t reflect this.

Given that JavaScript is primarily synchronous, the code in the program above did execute sequentially. But JavaScript supports asynchronous programming via features like the setTimeout() method.

The setTimeout() method is an asynchronous JavaScript method that takes two arguments: a function and a delay. The delay is a timer (in milliseconds), that delays the execution of the function. So, while the program above is waiting for the three seconds to execute the function in the setTimeout() method, it moves on to the next line in the code. This results in the execution of the third function call before the second.

Asynchronous JavaScript Technologies

Apart from the setTimeout() method mentioned above, several JavaScript technologies use asynchronous programming. These technologies use the asynchronous programming model to develop faster non-blocking applications. Some of these technologies include:

  • jQuery Ajax
  • Axios
  • NodeJS

Related: What Is Node.js? Here's How to Use Server-side JavaScript

Creating Asynchronous Programs With JavaScript

There are several ways to handle asynchronous code. The method that you choose should depend on the type of application you want to develop. These methods include callback functions, promises, and async/await.

Callback Functions

There are two important properties of a callback function. They serve as parameters for other functions, and they rely on external events to perform their duty. The setTimeout() method used in the asynchronous example above is a callback function. The program passes it a log function as a parameter (the callback function), and only executes it after three seconds (the event).

Callback functions are great for small programs, but as your applications grow, they can get too complicated very quickly. This is because callback functions often call other callback functions, creating a chain of nested callbacks.

Using Promises

JavaScript added support for promises after callback functions. They are a good alternative when creating larger applications. A promise represents what might happen after an asynchronous operation. This potential outcome will take one of two forms: resolved or rejected. A separate function handles each of these outcomes, removing the need for nesting (the callback function problem). Instead, promises encourage chain functions which are easier to use.

Every promise begins with a new Promise object that has an anonymous function with the resolve and reject parameters. Within this function, you’ll have the asynchronous application, which returns a resolve if the asynchronous operation succeeds, or a reject otherwise.

The then() chain function handles the resolve function, and the catch() chain function handles the reject function. So, there’s no need for nested if statements, as is the case with callback functions.

Using Promises Example

        const PromiseFunction = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("this asynchronous operation executed well")
        }, 3000)
    })
}
 
PromiseFunction().then((result) => {
    console.log("Success", result)
}).catch((error) => {
    console.log("Error", error)
})

The code above returns the following output in the console:

        Success this asynchronous operation executed well

This is because the promise returns the resolve function, which passes its results to the then() function. If the promise returns the reject function the program uses the catch function instead.

Using Async/Await

If you don’t want to create a promise chain when dealing with asynchronous operations, then you can try async/await. Async/await isn’t a completely different asynchronous tool from promises, just a different way of handling them. It handles promises without using the chain method. So, in much the same way that promises handle asynchronous operations better than callback functions, async/await has benefits over plain promises.

There are two key attributes of every async/await function. They start with the async keyword, and the await keyword waits for the result of an asynchronous operation.

Async/Await Program Example

        const PromiseFunction = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("this asynchronous operation executed well")
        }, 3000)
    })
}
 
const AsyncAwaitFunc = async () => {
    const result = await PromiseFunction();
    console.log(result);
}
 
AsyncAwaitFunc();

The code above will return the following output in the console:

        this asynchronous operation executed well

What Are the Major Takeaways?

There are several major points that you should take from this article:

  • Asynchronous programming is valuable because it reduces a program’s wait time, creating faster applications.
  • A callback function can be synchronous or asynchronous.
  • Promises offer a better way to handle asynchronous operations than callback functions.
  • Async/await functions handle promises in a better way than using chain functions.
  • An async/await function handles asynchronous operations in a way that looks synchronous, making it easier to understand.
  • Arrow functions help you to write better code.