DEV Community

Cover image for Javascript: How to access the return value of a Promise object
Katsiaryna (Kate) Lupachova
Katsiaryna (Kate) Lupachova

Posted on

Javascript: How to access the return value of a Promise object

Originally posted on my personal blog.

Intro (completely off-topic)

It's has been almost 3 months since my last blog post. There are reasons for that.

First, despite all precautions, I got sick with coronavirus (COVID-19) in the second half of June 2020. For two weeks it was total hell. Very bad well-being, I could only lie in bed and hope that it will go away soon. After that, it was a recovery for the next 2-3 weeks. Now I'm finally got back to normal life and even resumed my fitness training. So, coronavirus is no joke. Please, stay safe.

Second, there are lots of things happening right now in my home country - Belarus. Belarussians are fighting against dictatorship. Our (ex)-president lost last elections which were held on August 9th, 2020, but he continues to stay in power using brutal police and army forces against peaceful people and to threaten to anybody who disagrees with him. But we keep on fighting and to protest every day. I do take all these events very close to heart and hope to wake up one day in a free, democratic, and prosperous Belarus.

Now back to the topic.

What is a Promise in Javascript

A Promise is an object representing the eventual completion or failure of an asynchronous operation.

A Promise may be in one of the following states:

  • pending
  • fulfilled
  • rejected

One of the most widely used examples of asynchronous operations in Javascript is a Fetch API. The fetch() method returns a Promise.

Assume that we fetch some data from a backend API. For this blog post, I'll use JSONPlaceholder - a fake REST API. We will fetch a user's data with the id = 1:

fetch("https://jsonplaceholder.typicode.com/users/1")
Enter fullscreen mode Exit fullscreen mode

Let's see how we can access returned data.

1 - .then() chaining

It is the most simple and the most obvious way.

fetch("https://jsonplaceholder.typicode.com/users/1") //1
  .then((response) => response.json()) //2
  .then((user) => {
    console.log(user.address); //3
  });
Enter fullscreen mode Exit fullscreen mode

Here we (1) fetch data from the API, (2) transform it into JSON object and then (3) print user's address value to the console.

The result is:

{
  street: 'Kulas Light',
  suite: 'Apt. 556',
  city: 'Gwenborough',
  zipcode: '92998-3874',
  geo: { lat: '-37.3159', lng: '81.1496' }
}
Enter fullscreen mode Exit fullscreen mode

2 - Use returned value later in a code

But what if we'd like to use the returned value somewhere later in code?

If we try to do it like this (wrong way!):

const address = fetch("https://jsonplaceholder.typicode.com/users/1")
  .then((response) => response.json())
  .then((user) => {
    return user.address;
  });

console.log(address);
Enter fullscreen mode Exit fullscreen mode

We'll get

Promise { <pending> }
Enter fullscreen mode Exit fullscreen mode

It's happening because the Javascript code always executes synchronously, so the console.log() function starts immediately after the fetch() request, not waiting until it is resolved. In the moment when console.log() function starting to run, a Promise that should be returned from a fetch() request is in a pending status.

That said we can access the returned value of a Promise object in another .then() callback:

const address = fetch("https://jsonplaceholder.typicode.com/users/1")
  .then((response) => response.json())
  .then((user) => {
    return user.address;
  });

const printAddress = () => {
  address.then((a) => {
    console.log(a);
  });
};

printAddress();
Enter fullscreen mode Exit fullscreen mode

OR using async / await syntax:

const address = fetch("https://jsonplaceholder.typicode.com/users/1")
  .then((response) => response.json())
  .then((user) => {
    return user.address;
  });

const printAddress = async () => {
  const a = await address;
  console.log(a);
};

printAddress();
Enter fullscreen mode Exit fullscreen mode

In both ways, we'll get:

{
  street: 'Kulas Light',
  suite: 'Apt. 556',
  city: 'Gwenborough',
  zipcode: '92998-3874',
  geo: { lat: '-37.3159', lng: '81.1496' }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

A Promise object is widely used in Javascript async programming. And it's sometimes confusing for developers how to use it properly. In this blog post, I've attempted to describe a use case when a developer needs to use a returned value from a Promise object somewhere later in code.

Oldest comments (48)

Collapse
 
rishimagiawala profile image
rishimagiawala

Thank you so much! You have no idea how helpful this simple guide was for me. I really mean it. Thank you for taking the time to write this.

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

Thank you for such nice words! Happy to help!

Collapse
 
yickson profile image
Yickson Ramirez

Thank you!!! greetings from Chile.

Collapse
 
buraq911 profile image
Buraq Abdul Kareem

Thanks Kate, I've just start web applications coding and I wonder how can I manipulate the data instead of print it out only.

Thanks x

Collapse
 
r00tk1ll3r profile image
Monotheist

const address = fetch("jsonplaceholder.typicode.com/users/1")
.then((response) => response.json())
.then((user) => {
return user.address;
});

const printAddress = async () => {
const a = await address;
console.log(a);
};

let d = printAddress();
console.log(d); <-------- how do I do this? this still returns a Promise { }
I want to access return value from printAddress()

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

That's the whole point! You can use the return value from the Promise object ONLY in a async function.

You should do all the stuff that you'd like to do with the return result in a printAddress() async function.

Collapse
 
thechallengerr profile image
thechallengerr • Edited

But what if i had to take the return value of Promise to use as data to render ?
my case is that : I have to query database to get the link for 'src' attribute ? I use mongoosejs
Hope you can explain . Thank You

async getEventThumb(event_slug) {
            let event_thumb = Event.findOne({ event_slug: event_slug }).then((event) => {
                if (event === null) {
                    return ""
                } else {
                    event_thumb = event.event_thumb;
                }

                return event.event_thumb;
            }).catch((err) => {
                console.error(err);
            });

            // console.log(event_thumb);

            return await event_thumb;
        }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
younglotushuncho profile image
younglotushuncho

i find a new solution

the best way to use a promise ...... use a promise inside a promise ...it will work

Collapse
 
paint1024 profile image
paint1024

Really COOL and helpful stuff!
It saves me from Promise hell.
I spent hours on Stack Overflow and Google and fixed my need with this great article.

Although I can only learn about Belarus through news and Lev Vygotsky, I hope your country makes it.
Thank you again.
Best wishes from Taiwan.

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

Really happy that my blog post was helpful to you!

And thanks for your support! We (Belarusians) must win this fight!

Collapse
 
alexeyzyukov profile image
Alexey Zyukov

Thank for the explanation of code.
...when you win you'll understand that you loose, but too late. from Ukraine with best wishes.

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

Thank you for your nice words!
Glad to know that my blog post helped you with your project!

Collapse
 
artemtarasenko profile image
Artem

Well, that is not exactly a solution as far as I can understand the problem (or confusion if you will) that was supposed to be solved by this article.

In the first part, you are showing an assignment to a var "address" and then you are trying to log it, which returns a promise as was expected, right?

Then you are proposing to add another function and call "address" from the inside, but you DO NOT log "printAddress", you invoke it. You got logged data, but the same result could have been achieved by just logging the response in "address".

As for "printAddress", by making in async function you have converted it to a promise, so by trying to log it, you will get the same result as logging "address".

Correct me if I'm mistaken, but it seems to me your solution doesn't solve anything but only making the code bigger. The response date was logged from inside the promise and hasn't been extracted in any way.

The problem that you have tried to solve is definitely bothering a number of junior devs (me also as one of those juniors), however, I see no solution here. Moreover, I am, frankly, displeased to see unchecked, untrustworthy content here, no offense.

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova • Edited

The blog post consists of two parts:

  1. The first part describes how to access the return value of a Promise object right after it has been resolved
  2. The second part describes two possible ways of accessing the return value of Promise object LATER in the code. It's a completely another use case. Yes, the result is the same as when logging "address" variable (as it should be). But the main idea is to describe how to access this address value LATER in the code.

Probably you have another use case, that's why this solution doesn't meet your needs. If you could share the problem that you are trying to solve, maybe we could discuss the possible solution.

Collapse
 
jaballadares profile image
John Balladares

Thank you so much for this!!

Collapse
 
nasarmientoo profile image
nasarmientoo

Hey! It was really helpful.
I'm trying to do this with an array of promises, what would be the async method?

Collapse
 
nasarmientoo profile image
nasarmientoo

Hey! It was really helpful.
I'm trying to do this with an array of promises, what would be the async method?