Learn how to retrieve the result of an asynchronous function, whether it is promise-based or callback-based, using JavaScript.

Imagine you encounter this scenario: you need to return the result of an asynchronous call from the original function. Here is a simplified example:

const mainFunction = () => {
  const result = asynchronousFunction();
  return result;
}

However, asynchronousFunction() performs an asynchronous operation, such as a fetch() call, and cannot directly return the result value. It may rely on promises or callbacks internally, like below:

const asynchronousFunction = () => {
  return fetch('./file.json').then(response => {
    return response;
  });
}

What can you do in this situation?

One straightforward solution is to use async/await. You can replace the promise-based approach with the await keyword, as demonstrated in the updated asynchronousFunction():

const asynchronousFunction = async () => {
  const response = await fetch('./file.json');
  return response;
}

To accommodate this change, you’ll need to add the async keyword to the function signature of mainFunction, and use await before calling asynchronousFunction():

const mainFunction = async () => {
  const result = await asynchronousFunction();
  return result;
}

Now, since mainFunction is an async function, it returns a promise:

mainFunction(); // returns a Promise

To retrieve the result, you can wrap this code in an Immediately Invoked Function Expression (IIFE):

(async () => {
  console.log(await mainFunction());
})();

This code gives the impression of synchronous programming, despite being fully asynchronous.

Alternatively, you can leverage callbacks. However, unlike async/await, where only asynchronousFunction() needs modification, here you need to make changes to asynchronousFunction(), mainFunction(), and the calling code.

Here’s an example. asynchronousFunction() now receives a new function parameter called callback, which it invokes by passing the response object:

const asynchronousFunction = callback => {
  return fetch('./file.json').then(response => {
    callback(response);
  });
}

The callback function is provided by mainFunction:

const mainFunction = () => {
  const callback = result => {
    console.log(result);
  }

  asynchronousFunction(callback);
}

The final step is modifying the calling function, as we cannot return the response directly from mainFunction. Since the retrieval is asynchronous, the calling function needs to adapt:

Instead of const result = mainFunction(), you can use:

const callbackFunction = result => {
  console.log(result);
}

const mainFunction = callback => {
  asynchronousFunction(callback);
}

// Call the code

mainFunction(callbackFunction);