node.js
promise resolution
async programming
JavaScript
return value

node.js resolve promise and return value

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The core rule in Node.js is simple: if a function does asynchronous work, you cannot return its final value synchronously. You must either return a Promise and let the caller await it, or continue the workflow inside a .then() chain. Most confusion comes from trying to assign a future value to a normal variable and use it immediately.

The Wrong Mental Model

This pattern does not work:

javascript
1function getUserName() {
2  let result;
3
4  Promise.resolve("Ava").then(value => {
5    result = value;
6  });
7
8  return result;
9}
10
11console.log(getUserName()); // undefined

The function returns before the Promise settles. result gets assigned later, after the synchronous part has already finished.

Return the Promise Instead

If the function is asynchronous, return the Promise itself.

javascript
1function getUserName() {
2  return Promise.resolve("Ava");
3}
4
5getUserName().then(name => {
6  console.log(name);
7});

This is the basic Promise contract: the caller receives a Promise now and the actual value later.

Use async and await

In modern Node.js, async and await are usually the clearest way to express the same idea.

javascript
1async function getUserName() {
2  return "Ava";
3}
4
5async function main() {
6  const name = await getUserName();
7  console.log(name);
8}
9
10main().catch(console.error);

An async function always returns a Promise, even when it looks like it returns a plain value.

Real Example with File I/O

Asynchronous confusion shows up most often with filesystem or network operations.

javascript
1const fs = require("fs/promises");
2
3async function readConfig() {
4  const text = await fs.readFile("config.json", "utf8");
5  return JSON.parse(text);
6}
7
8async function main() {
9  const config = await readConfig();
10  console.log(config);
11}
12
13main().catch(console.error);

Here readConfig() does not return the parsed object directly to synchronous code. It returns a Promise that resolves to the parsed object.

Transforming Promise Results

You can return a derived value from a .then() callback, and that derived value becomes the resolution of the next Promise in the chain.

javascript
1Promise.resolve({ first: "Ava", last: "Li" })
2  .then(user => `${user.first} ${user.last}`)
3  .then(fullName => {
4    console.log(fullName);
5  });

That is how you “return a value from a Promise”: not by breaking out into synchronous code, but by returning from the async continuation.

Returning from Nested Callbacks

Another common bug is returning from inside a .then() and expecting it to return from the outer function.

javascript
1function broken() {
2  Promise.resolve(42).then(value => {
3    return value;
4  });
5}
6
7console.log(broken()); // undefined

The return value only returns from the callback passed to .then(). It does not return from broken().

Correct version:

javascript
1function fixed() {
2  return Promise.resolve(42).then(value => {
3    return value;
4  });
5}
6
7fixed().then(console.log);

Handling Errors

When you return Promises, error handling has to stay in the async path too.

javascript
1async function getData() {
2  throw new Error("Request failed");
3}
4
5async function main() {
6  try {
7    await getData();
8  } catch (err) {
9    console.error("caught:", err.message);
10  }
11}
12
13main();

If you forget to await or attach .catch(), rejections can escape and become unhandled Promise warnings or process failures depending on your runtime and settings.

Multiple Async Values

When you need several async results, combine them instead of forcing them into synchronous variables.

javascript
1async function main() {
2  const [a, b] = await Promise.all([
3    Promise.resolve(10),
4    Promise.resolve(20)
5  ]);
6
7  console.log(a + b);
8}
9
10main();

This keeps the whole flow in the Promise model rather than pretending the values already exist.

Common Pitfalls

The most common mistake is trying to return an asynchronously computed value from a synchronous function. Another is believing that return inside .then() returns from the outer function, when it only returns from the callback. Developers also often mix await and plain function calls inconsistently, which makes control flow harder to follow. Finally, forgetting to handle Promise rejection leaves async errors unobserved until runtime.

Summary

  • You cannot synchronously return the future result of a Promise.
  • Return the Promise itself or make the function async.
  • Use await or .then() in the caller to access the resolved value.
  • A return inside .then() only affects the Promise chain, not the outer function.
  • Keep error handling in the async path with try and catch or .catch().

Course illustration
Course illustration

All Rights Reserved.