JavaScript
asynchronous
synchronous
request handling
return value

Return value from asynchronous OR synchronous JavaScript request

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

The most important rule here is simple: you cannot return the final result of an asynchronous request as if it were already available synchronously. The outer function returns before the network callback finishes. Once that timing model is clear, the solution becomes choosing one of the correct asynchronous patterns: callback, promise, or async and await.

Why the Naive Return Fails

This pattern does not work:

javascript
1function getUser() {
2  fetch('/api/user')
3    .then(response => response.json())
4    .then(data => {
5      return data;
6    });
7}
8
9const user = getUser();
10console.log(user);

getUser() returns immediately, long before the network response arrives. The return data only returns from the inner callback, not from getUser() itself.

This is the core mental model mistake behind most questions on this topic.

Return a Promise Instead

A correct asynchronous wrapper returns a promise.

javascript
1function getUser() {
2  return fetch('/api/user')
3    .then(response => response.json());
4}
5
6getUser().then(user => {
7  console.log(user);
8});

Now the caller can wait for the eventual result properly. The function is still returning something immediately, but that something is a promise representing future completion rather than the final data itself.

async and await Make the Code Read Better

The same logic becomes easier to read with async and await.

javascript
1async function getUser() {
2  const response = await fetch('/api/user');
3  return response.json();
4}
5
6async function main() {
7  const user = await getUser();
8  console.log(user);
9}
10
11main();

await does not make the request synchronous in the old blocking sense. It only makes the asynchronous control flow easier to express.

This is the modern default for most JavaScript application code.

Callbacks Still Explain the Model Clearly

Before promises, callback-based APIs made the timing model explicit.

javascript
1function getUser(callback) {
2  fetch('/api/user')
3    .then(response => response.json())
4    .then(data => callback(null, data))
5    .catch(err => callback(err));
6}
7
8getUser((err, user) => {
9  if (err) {
10    console.error(err);
11    return;
12  }
13  console.log(user);
14});

You may still see this pattern in older code or APIs built on Node.js conventions. It is useful to understand even if promises are now more common.

Synchronous Requests Exist, but They Are Usually the Wrong Answer

Historically, synchronous XHR existed and allowed code that looked like it returned a request result directly. But synchronous network requests block the main thread and are heavily discouraged in browsers.

javascript
1const xhr = new XMLHttpRequest();
2xhr.open('GET', '/api/user', false);
3xhr.send(null);
4console.log(xhr.responseText);

This blocks execution and harms responsiveness. In browser code, it is generally the wrong approach and may be restricted or deprecated depending on the context.

If you think you need a synchronous request, the more likely reality is that the surrounding code needs to become asynchronous too.

Move the Dependent Logic Inside the Async Flow

A common design improvement is not trying to extract the async result too early. Instead, move the code that needs the result inside the promise chain or async function.

javascript
1async function loadProfilePage() {
2  const user = await getUser();
3  renderProfile(user);
4}

This is often the real solution. The issue is not "how do I return the async value synchronously." The issue is "how do I structure the dependent logic so it runs when the value is ready."

That shift in design thinking makes asynchronous code much easier to maintain.

Common Pitfalls

  • Trying to return from inside a callback and expecting the outer function to receive that value synchronously.
  • Treating promises as if they already contain the resolved value.
  • Using synchronous XHR in browser code to avoid learning asynchronous flow.
  • Writing one async helper correctly but leaving all caller code structured as if it were synchronous.
  • Forgetting to propagate errors through promise chains or try/catch around await.

Summary

  • You cannot return an asynchronous request result as an already available synchronous value.
  • Return a promise or use async and await instead.
  • Callbacks, promises, and async functions all model the same timing reality.
  • Synchronous browser requests are generally discouraged and usually the wrong fix.
  • The real solution is often restructuring dependent logic to run when the async result arrives.

Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Basis Lab
No course covers this one yet

Basis Lab writes one for you from a sentence about what you want to be able to do, then teaches it and checks you understood. Your first course is free.

Build my course
Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions