I have the following code,
let currencyValues = [];
const retrieveCurrencyPairs = async (pair) => {
const r = await fetch(pair.url);
const rParsed = await r.json();
let newCurrencyValue = { currency: pair.countries, value: rParsed };
return newCurrencyValue;
};
useEffect(() => {
currencyValues = currencyPairs.map(retrieveCurrencyPairs);
console.log(currencyValues);
}, []);
and the following expectations:
- On page load, the
useEffect
triggers the function inside of the map() - For each value of the array, the
retrieveCurrencyPairs()
is triggered and awaits for the result, which is then returned - The
currencyValues
array is the filled with the 3 new objects
Unfortunately the function is returning promises, instead of the objects.
Any tip on how to return the objects instead?
CodePudding user response:
async functions always return promises. You could do this instead:
Promise.all(currencyPairs.map(retrieveCurrencyPairs))
.then( results => ... )
Promise.all has the additional benefit of running them all in parallel instead of sequentially.
You might consider Promise.allSettled if you want to deal with individual failures/rejections without rejecting the whole list.
CodePudding user response:
I think you should use Promise.all
in order to properly handle multiple promises
useEffect(() => {
(async()=>{
const results = await Promise.all(currencyPairs.map(retrieveCurrencyPairs))
console.log(results );
})()
}, []);
OR
useEffect(() => {
const results = Promise.all(currencyPairs.map(retrieveCurrencyPairs)).then(results => console.log(results));
}, []);
To learn more about Promise.all
or To learn more about Promise.allSettled
use MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
CodePudding user response:
Try this
useEffect(() => {
(async()=>{
currencyValues = await currencyPairs.map(retrieveCurrencyPairs);
console.log(currencyValues);
})()
}, []);
CodePudding user response:
In the code you provided, retrieveCurrencyPairs is an async function, which means that it returns a promise that resolves to the return value of the function. This means that currencyValues will be an array of promises, rather than an array of objects.
To fix this, you can use the await keyword inside of the map function to wait for the promises to resolve before assigning the result to currencyValues. You will also need to make the useEffect function async so that you can use await inside of it. Here's an example of how you could do this:
const retrieveCurrencyPairs = async (pair) => {
const r = await fetch(pair.url);
const rParsed = await r.json();
let newCurrencyValue = { currency: pair.countries, value: rParsed };
return newCurrencyValue;
};
const useEffect = async (() => {
currencyValues = await Promise.all(currencyPairs.map(retrieveCurrencyPairs));
console.log(currencyValues);
}, []);
This code will wait for all of the promises returned by retrieveCurrencyPairs to resolve before assigning the result to currencyValues. This means that currencyValues will be an array of objects, rather than an array of promises.
CodePudding user response:
async functions always return promises even implicitly. You need to either await the currency.Pairs.map(retrieveCurrencyPairs)
either .then
it
Since a Promise.all
answer is already posted and is a good practice to stick with one approach, here is the alternative with await
useEffect(() => {
const getCurrencyValues = async ()=>{
const currencyValues = await currencyPairs.map(retrieveCurrencyPairs);
return currencyValues
}
console.log(getCurrencyValues());
}, []);