DEV Community

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

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

Katsiaryna (Kate) Lupachova on August 24, 2020

Originally posted on my personal blog. Intro (completely off-topic) It's has been almost 3 months since my last blog post. There are re...
Collapse
 
davestewart profile image
Dave Stewart • Edited

It's really important to note that the Promise object doesn't return a value, it resolves a value via the then() method.

It is the fetch() function that returns a value, which is a Promise instance.

It is the Promise instance on which you call the then() method, passing in a callback function, which will be eventually be fired when the async code finishes (and internally, calls resolve()).

As an example, here's what a custom load function might look like:

function load (url) {
  return new Promise(async function (resolve, reject) {
    // do async thing
    const res = await fetch(url)

    // your custom code
    console.log('Yay! Loaded:', url)

    // resolve
    resolve(res.json()) // see note below!
  })
}

// run the function and receive a Promise
const promise = load('https://...')

// let the Promise know what you want to do when it resolves
promise.then(console.log)
Enter fullscreen mode Exit fullscreen mode

Note that the Promise object will resolve any nested promises as part of its work, so resolving res.json() which results in a Promise being created will be resolved internally before the final chained .then(console.log) is called.

The trick to Promises is:

  1. always return Promises you create (or functions that return Promises) so they can be chained
  2. always resolve() or reject() within the promise executor so .then() or .catch() will be called and the chaining will complete
Collapse
 
uzomao profile image
uzoma

Created an account just to say thank you for this breakdown.

Collapse
 
davestewart profile image
Dave Stewart

Well that's very kind of you. I'm glad it helped!

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
 
irina_kats profile image
Irina Kats

I am another one who created an account to say Thank You to Kate for the article and @davestewart for amplifying it! I've been having this trouble too and wanted to understand what I am doing wrong. Now I seem to understand it.

Collapse
 
tomknn profile image
TomKnn

Hi Kate,

Thanks for the article.
I only get results when I write down the code (with my own api endpoint) like this:
fetch("https://api.spoonacular.com/recipes/complexSearch?number=2&apiKey=b4408aa9ab144e47ae2bf8eff93e72f5")
.then((response) => response.json())
.then((user) => {
console.log(user)
});

I don`t understand what you mean by console.log(user.address) or how to adapt this into your own code.

Anyway, from the results:
results: Array(2)
0: {id: 716426, title: 'Cauliflower, Brown Rice, and Vegetable Fried Rice', image: 'spoonacular.com/recipeImages/71642...', imageType: 'jpg'}
1: {id: 715594, title: 'Homemade Garlic and Basil French Fries', image: 'spoonacular.com/recipeImages/71559...', imageType: 'jpg'}
length: 2

I want to make an array with only the recipe numbers, something like this:
recipeArray = [716426, 715594] and use this for a declaration like let defaultIndex = recipeArray[0];- for another piece of code.

Do you know how to do this? I`d be very grateful.

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

You can try something like that:

const getRecipes = async () => {
fetch("https://api.spoonacular.com/recipes/complexSearch?number=2&apiKey=b4408aa9ab144e47ae2bf8eff93e72f5")
.then((response) => response.json())
.then((user) => {
const recipes = user.results.map(result => result.id)
console.log(recipes)
return recipes
});
}

const recipes = await getRecipes();

You'll get an array of recipe ids.

Collapse
 
tomknn profile image
TomKnn

Hi Kate,

Thank you so much for your time and trouble, I appreciate!
I've tried your code but I get this error because of the 'const recipes = await getRecipes()' line:
Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules

Do you have any suggestions? Api fetch is pretty new to me and my vocabulary with this is limited.

Thread Thread
 
ramonak profile image
Katsiaryna (Kate) Lupachova

could you please DM me or provide me a link to your code somewhere online (github repo, code sanbox and so on), so I could take a look and try to help you?

Thread Thread
 
tomknn profile image
TomKnn

Sure, it`s github.com/TomKnn/EindopdrachtMood....
To give you some context, I'm re-educating from illustrator/'art'teacher to front end developer due to lack of work opportunities. I like it very much but the course is online with little help, I'm stuck for months now on little things.
This is my final assignment where we have to a modest site design with an api function.
It's a bit of a mess, but I'll tweak it as soon as my code works.
The files you need are here github.com/TomKnn/EindopdrachtMood...
And here is the main.js where I want to import the function.
github.com/TomKnn/EindopdrachtMood...

Pls let me know if something is unclear, many thanks!!
Tom

Collapse
 
gloriaconcepto profile image
gloriaconcepto

First of all i guess you are feeling ok,secondly i send my positive thoughts of love peace to your country.Lastly thanks i was in a hell trap .but your articles has really help to sort it out one Love .

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

Thank you very much! Appreciate your words!

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
 
smallbasic profile image
small-basic

how comes you are invoking the "address" function without any parenthesis.

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

total noob question here i guess, but would appreciate if someone can direct me to the right resource to learn this further , tia

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

because "address" in not a function here, but a variable to which the return value of the fetch request is assigned to

Collapse
 
smallbasic profile image
small-basic

thanks for the reply.

Just one last question, if the "address" is a variable which stores the result of the fetch query, then what is triggering the fetch call ?.

Thread Thread
 
ramonak profile image
Katsiaryna (Kate) Lupachova

once the interpreter ((like the JavaScript interpreter in a web browser) ) reaches the code with the fetch() function, it adds it to the call stack list. We just assign the result (the return value) of this async function in order to have access to it later.

The call stack order is really easy to test. If we update the code like this:

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

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

console.log("RUN");
printAddress();
Enter fullscreen mode Exit fullscreen mode

The result in the console will be:
RUN
PRINT ADDRESS
FETCH RETURN

The fetch function is being executed without any additional trigger or call. But we get its result after all other functions because fetch takes more time to complete its job. And as fetch is an asynchronous function, it's not blocking other functions.

Thread Thread
 
smallbasic profile image
small-basic

thank you so much

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
 
johnnyrubi profile image
Johnny Rubi

Hello friend, I'm a Brazilian guy who spent 10 hours trying to understand why I couldn't get the result from my API, I spent hours trying to find an answer on the internet on all possible pages and I didn't understand or found any answer, I ended up on your blog and wanted to thank you , I signed up on this site just to comment that your job saved me in every way possible, as I needed it to get a job! please don't stop your blog! you are awesome! and teaches very well! thanks!

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

Hi Johnny! Thank you for such nice words! It means a lot to me!
The main reason why I write blog posts is to share my knowledge with fellow developers so we could help each other.

Collapse
 
aumartinez profile image
Augusto Martinez

This brought light to an issue I had after being hours looking over the internet, I am just curios that on my implementation (using Vue.js), the first solution works only when arrow functions are used, if I try to convert the arrow function to a regular function, the promise value is never returned.

Collapse
 
onlykingkd profile image
Kaustubh Dwivedi

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

const printAddress = async () => {
const a = await address;
return a;
};

*Console.log(a) inside printAddress is working fine but :
Now I need to call this printAddress inside the return of a react Component thats why I am returning 'a' from printAdress, there it is showing promise pending. Is there any way to solve this ? *

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

could you provide a piece of code of your react component? it would be easier to understand and will try to help.

Collapse
 
stefcab profile image
stefcab

You could even simplify without using an other function:

const printAddress = () => {
  address.then((a) => {
    console.log(a);
  });
};
Enter fullscreen mode Exit fullscreen mode

to

address.then((a) => {
    console.log(a);
  });
Enter fullscreen mode Exit fullscreen mode
Collapse
 
metawops profile image
Stefan Wolfrum

Great article, helped me a lot to understand this concept! 👍👍
One question: suppose this fetch() call is inside a function. How would I return the JSON object from that function back to the main JS area where I made the call to the function? I tried a "return a;" just after the "console.log(a);" but that didn't work. Then I tried "return printAddress();", which didn't work either.
Any help? 😳

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

I'd say that the only way to get this JSON object outside the fetch() call is to assign it to a variable. If you could provide your piece a code it would be easier to understand and to help:)

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
 
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
 
sadaf_sajad_d2027c3f81a83 profile image
Sadaf Sajad

Hi, Kate
Can you please help me with this one
i receive data from an axios call collect it in a variable and return it when i call the function i receive data as promise like you showed
i put async await everything you said but this isn't working

$(document).ready(function () {
merchantDetails;
var load = merchantDetails(userName)
console.log(load)
})
merchantDetails = function (userName) {
var axiosResponse = axios.get("/adminMerchantOrderDetails/merchantDetails?username=" + userName).then(function (response) {
let order = response.data.responseData;
return order
console.log((order))
})
return axiosResponse
}

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

Hi Sadaf! It's kinda hard to understand this unformatted piece of code. Could you please provide a link to a codesanbox, GitHub repo or something like that so I could take a look and try to help you?

Collapse
 
jaballadares profile image
John Balladares

Thank you so much for this!!

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
 
fs10218 profile image
fs10218 • Edited

Thank you, this article was very helpful;
But you did not say how to call the Promise value elsewhere and just print it on the console
Wishing you victory and success
from Iran

Collapse
 
engineerscodes profile image
NAVEEN

Thanks helped me a Lot

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?

Collapse
 
yickson profile image
Yickson Ramirez

Thank you!!! greetings from Chile.

Collapse
 
eldhose profile image
eldhose

thanks!

Collapse
 
rtf747 profile image
Rumer Tovar

Thank you very much for such an excellent article. I had the same problem but with axios and it worked perfectly

Collapse
 
ramonak profile image
Katsiaryna (Kate) Lupachova

Thank you! Happy that it helped you to solve your problem!