~/ What is an Asynchronous Function in Programming?

You will know about what is asynchronous function in programming. What is it and why we use it. You will also know how to use it in your code.

May 25, 2025

|

7 min read

Web Development
JavaScript
Programming

An asynchronous function in programming refers to a function that operates without blocking the main execution thread. This means that while an asynchronous operation is in progress (like fetching data from an API or reading a file), the rest of the code continues to run. This non-blocking nature is especially important in environments like web browsers or servers, where responsiveness and performance are critical.

Synchronous functions execute one line at a time, and each step must complete before the next begins. This can lead to poor performance or freezing behavior in applications, particularly when dealing with tasks such as:

  • HTTP requests to servers
  • File system access
  • Database queries
  • Timers or intervals
  • Waiting for user input

Asynchronous programming allows your application to handle multiple tasks in parallel and improves overall responsiveness.

JavaScript provides several ways to work with asynchronous behavior:

A callback is a function passed as an argument to another function. It's executed after the outer function finishes its operation.

TypeScript

function fetchData(callback: () => void) { setTimeout(() => { console.log("Data fetched."); callback(); }, 2000); } fetchData(() => { console.log("Callback executed."); });

A Promise represents a value that might not be available yet but will be resolved in the future.

TypeScript

const promise = new Promise((resolve, reject) => { setTimeout(() => { resolve("Promise resolved"); }, 2000); }); promise.then((message) => { console.log(message); });

Introduced in ES2017, async and await simplify working with Promises. They make asynchronous code look and behave more like synchronous code.

TypeScript

async function fetchMessage() { const result = await new Promise<string>((resolve) => { setTimeout(() => { resolve("Async/Await resolved"); }, 2000); }); console.log(result); } fetchMessage();

One of the most basic examples of asynchronous behavior in JavaScript is the setTimeout function. This function allows you to delay execution of a piece of code without blocking the rest of the program.

TypeScript

let x: number = 10; console.log("Value of x is " + x); callXAfterSec({ seconds: 5 }); function callXAfterSec({ seconds }: { seconds: number }) { setTimeout(() => { console.log("Called X after " + seconds + " seconds" + " with value " + x); }, seconds * 1000); }

$Terminal

Value of x is 10 // (5 seconds later...) Called X after 5 seconds with value 10

In the above code:

  • The initial value of x is printed immediately.
  • The callXAfterSec function uses setTimeout to schedule another log after a 5-second delay.
  • Meanwhile, the program does not pause or freeze-it simply continues.

Here's a clear example comparing non-blocking async behavior vs blocking synchronous code.

JavaScript

function doOtherThings() { console.log("Doing other things while waiting..."); } // Simulate a slow network call using async/await async function fetchData() { console.log("Start fetching data..."); await new Promise(resolve => setTimeout(resolve, 3000)); // 3-second delay console.log("Data fetched!"); } async function main() { fetchData(); // starts the async function doOtherThings(); // runs immediately, doesn't wait for fetchData to finish } main();

Output:

$Terminal

Start fetching data... Doing other things while waiting... (wait 3 seconds...) Data fetched!

JavaScript

function fetchData() { console.log("Start fetching data..."); const start = Date.now(); while (Date.now() - start < 3000) { // do nothing - just block } console.log("Data fetched!"); } function doOtherThings() { console.log("Doing other things..."); } function main() { fetchData(); doOtherThings(); // this will only run after fetchData finishes } main();

Output:

$Terminal

Start fetching data... (wait 3 seconds...) Data fetched! Doing other things...

As you can see, in the blocking version, the whole program pauses during the delay. The asynchronous version allows other parts of the code to run while waiting.

Use asynchronous functions when:

  • The task takes time (e.g., network or file system operations)
  • You want to maintain responsiveness (e.g., in user interfaces)
  • You're dealing with external dependencies (e.g., APIs, databases)
  • You want to avoid blocking the event loop or main thread

  • Improved Performance: Non-blocking operations allow faster execution of concurrent tasks.
  • Responsive Applications: UIs remain interactive even during long-running processes.
  • Efficient Resource Usage: No unnecessary waiting or pausing in the application flow.

Asynchronous functions are fundamental for modern programming, particularly in environments like JavaScript where single-threaded execution can lead to performance bottlenecks. By leveraging callbacks, promises, or async/await, you can handle time-consuming operations without interrupting the flow of your application.

Understanding and correctly implementing asynchronous programming patterns will help you write cleaner, more efficient, and more maintainable code.

If you're building modern web applications, learning how to use asynchronous functions effectively is a must. Start with simple examples like setTimeout, then progress to working with Promises and async/await for better control and readability.