How to return the response from an asynchronous call in Javascript?

Asynchronous programming is common in JavaScript network programming. In this approach, we can download data or perform time-dependent operations without blocking the current execution flow. This article explores techniques to return responses from asynchronous calls in JavaScript.

Before diving into solutions, let's examine a common problem developers face with asynchronous calls:

The Problem

function aTrivialFunction() {
   ajaxCall(..., function onSuccess(result) {
      // How do we return result from this function?
   });
}
console.log('result of aTrivialFunction:', aTrivialFunction()); // undefined

This AJAX call represents a general pattern: trying to synchronously return the result of an asynchronous function. This is not directly possible in JavaScript because the function returns before the callback executes.

Types of Asynchronous Functions

  • Callbacks ? Functions passed as parameters to other functions, called when the operation completes. The callback receives the result as a parameter.

  • Promises ? Objects that represent the eventual completion of an asynchronous operation. A promise can be:

    ? Pending: Initial state, neither fulfilled nor rejected

    ? Fulfilled: Operation completed successfully

    ? Rejected: Operation failed

  • Async/Await ? Keywords that make asynchronous code look more synchronous and improve readability.

Solution: Using Promises

Instead of trying to return values directly, we return a Promise that resolves with the result:

function fetchData() {
   return new Promise((resolve, reject) => {
      // Simulating an AJAX call with setTimeout
      setTimeout(() => {
         const result = { message: "Data fetched successfully!" };
         resolve(result);
      }, 1000);
   });
}

async function main() {
   console.log("Starting async operation...");
   const result = await fetchData();
   console.log("Result:", result);
}

main();
Starting async operation...
Result: { message: 'Data fetched successfully!' }

Using Async/Await in Global Context

Since await can only be used inside async functions, we wrap our code in an immediately invoked async function:

function simulateApiCall() {
   return new Promise((resolve) => {
      setTimeout(() => {
         resolve("API response data");
      }, 500);
   });
}

(async () => {
   console.log("Calling API...");
   const response = await simulateApiCall();
   console.log("Response:", response);
   console.log("Operation complete!");
})();
Calling API...
Response: API response data
Operation complete!

Handling Errors

Promises also handle error cases using the reject function:

function riskyOperation() {
   return new Promise((resolve, reject) => {
      setTimeout(() => {
         const success = Math.random() > 0.5;
         if (success) {
            resolve("Operation successful");
         } else {
            reject(new Error("Operation failed"));
         }
      }, 300);
   });
}

async function handleRiskyOperation() {
   try {
      const result = await riskyOperation();
      console.log("Success:", result);
   } catch (error) {
      console.log("Error:", error.message);
   }
}

handleRiskyOperation();

Comparison of Approaches

Approach Readability Error Handling Browser Support
Callbacks Poor (callback hell) Complex All browsers
Promises Good Better ES6+
Async/Await Excellent Simple with try/catch ES2017+

Conclusion

You cannot transform asynchronous functions into synchronous ones in JavaScript. Instead, use Promises with async/await to write clean, readable code that handles asynchronous operations effectively. This approach maintains the benefits of non-blocking execution while providing synchronous-like syntax.

Updated on: 2026-03-15T23:18:59+05:30

491 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements