BlogHow to return a value from an asynchronous function (JavaScript)

How to return a value from an asynchronous function (JavaScript)

8/3/2021, 1:14:39 PM
javascript webdev

(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);
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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 })
}
Enter fullscreen mode Exit fullscreen mode

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);
    })
}
Enter fullscreen mode Exit fullscreen mode

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);
    })
}
Enter fullscreen mode Exit fullscreen mode

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);
    }
})();
Enter fullscreen mode Exit fullscreen mode

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]

0%