Ever tried returning a value from an asynchronous function in JavaScript and received `undefined` instead?…
Ever tried returning a value from an asynchronous function in JavaScript and received undefined instead?
Here is a classic trap most developers hit early on:
function fetchUserData() {
let user;
setTimeout(() => {
user = { name: "Ali" };
}, 2000);
return user;
}
const result = fetchUserData();
console.log(result); // undefined
Why does this happen, even if you wait 2 seconds?
1. JavaScript Does Not Wait
JavaScript executes code synchronously on a single Call Stack.
When fetchUserData() runs, it hands the 2-second timer to the browser's background engine and immediately moves to the next line: return user;.
At that split second, user has not been assigned a value yet, so it returns undefined. The outer function has already finished execution long before the timer completes.
2. Can We Just Return Inside setTimeout?
function fetchUserData() {
setTimeout(() => {
const user = { name: "Ali" };
return user; // Where does this go?
}, 2000);
}
This still fails. That return statement belongs to the nested anonymous callback, not fetchUserData. It returns a value back to the browser's internal timer trigger, leaving your outer function empty.
3. The Fix: The Callback Pattern
Because asynchronous tasks cannot return values synchronously, we invert the flow. Instead of expecting data to return upward, we pass a function inward:
function fetchUserData(callback) {
setTimeout(() => {
const user = { name: "Ali" };
callback(user); // Delivering data once ready!
}, 2000);
}
fetchUserData((data) => {
console.log("Data received:", data); // { name: "Ali" }
});
A callback is simply a function passed as an argument to another function so it can be invoked later once background work completes.