How to return a value from an asynchronous function (JavaScript)
(Originally posted on https://dev.to/debadeepsen/how-to-return-a-value-from-an-asynchronous-function-javascript-1k1h)
Consider the following code. Suppose, you have a function, and what you want it to do is return a certain value after 5 seconds. So, you do this.
function getValue() {
setTimeout(() => {
return 42;
}, 5000);
}
This won't work. Why? Because you're really returning from the callback function that is acting as the first argument of setTimeout
. Essentially, what you're doing is this -
function getValue() {
function cb() {
return 42;
}
setTimeout(cb, 5000);
}
As you can see, getValue
isn't returning anything here.
You might face the same problem while making other similar asynchronous calls, like using the fetch
API (or other Promise-based API) for example.
function getUserList() {
fetch("users.json")
.then(r => r.json())
.then(d => { return d })
}
You can take multiple approaches, but I'm just going to talk about the most simple one - building your own Promise using the constructor function and returning it. Let's try to modify the getValue
function using Promises.
function getValue() {
return new Promise(resolve => {
setTimeout(() => {
resolve(42);
}, 5000);
})
}
A Promise constructor, if you recall, takes a callback function as its only parameter, which in turn takes in two callbacks, resolve and reject, which determine if the promise was fulfilled or rejected, accordingly. If you wanted, you could modify the code above to include a rejection criterion:
function getValue() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(Math.random() > 0.5)
resolve(42);
else
reject(-1);
}, 5000);
})
}
A
Promise
is an object that will hold a value in the future.
And now that the function works this way, you can easily call it with an async
/await
combo to make it look like it was synchronous. (The await
keyword pauses the program execution until the Promise it's acting upon is settled)
(async function () {
try {
// promise resolution
let meaningOfLife = await getValue();
console.log(meaningOfLife);
}
catch (e) {
// promise rejection
console.error(e);
}
})();
I've wrapped it in an immediately-invoked function expression (IIFE), but you could easily do it with a regular
async
function.
Hope that helped!
[Photo by Adi K from Pexels]