Returning promises in javascript - javascript

I need some help returning a promise. I don't get why I am not getting the players value
The code
const playerSelectName = document.getElementById('sel1');
const playerSelectPosition = document.getElementById('sel2');
const playerSelectAge = document.getElementById('sel3');
const searchButton = document.getElementById('search-btn');
async function getPlayers() {
const response = await fetch('https://football-players-b31f2.firebaseio.com/players.json?print=pretty');
const playersObject = await response.json();
return playersObject;
}
searchButton.addEventListener('click', async () => {
const players = await getPlayers();
let [ name, position, age ] = [ playerSelectName.value, playerSelectPosition.value, playerSelectAge.value ];
yersObject.filter((playerAge) => {});
});
I cant get to access the code inside my listener function of the value players

the problem was in destructuring check the below snippet. I hope this will solve the issue . Also please update what you are trying to achieve in filter so i can add on the solution.
I didnt understood what are you trying to do in destructure part and after that filter
async function getPlayers() {
const response = await fetch('https://football-players-b31f2.firebaseio.com/players.json?print=pretty');
const playersObject = await response.json();
return playersObject;
}
const searchButton = document.getElementById('search-btn');
searchButton.addEventListener('click', async () => {
const players = await getPlayers();
players.forEach(player => {
const {name, nationality, position} = player
console.log(name, nationality, position)
})
});
<button id='search-btn'>
Load Results
</button>

Here's a simple example accessing the players to help get you started.
async function getPlayers() {
const response = await fetch('https://football-players-b31f2.firebaseio.com/players.json?print=pretty');
return response.json();
}
(async () => {
const players = await getPlayers();
console.log(players)
})();

Related

unable to display data dynamically using fetch API

I am facing problems while displaying data fetched dynamically from an API. console log clearly shows that the promise has been fulfilled and the data has been successfully fetched but the data is somehow not getting displayed in the relevant container. I am using map method of arrays to dynamically display data using template strings. An inspection of the page also does not mentions any related errors in the code. what could be the problem?
const url = 'https://api.github.com/users/john-smilga/followers?per_page=100'
const fetchFollowers = async() => {
const response = await fetch(url);
const data = await response.json();
return data;
}
const getData = fetchFollowers();
const place = document.getElementById("container")
const display = () => {
let newFollowers = getData.map((item) => {
const {
avatar_url,
login,
html_url
} = item;
return `<article class="card">
<img src="${avatar_url}">
<h4> ${login}</h4>
view profile
</article>`;
})
.join(" ");
place.innerHTML = newFollowers;
}
<div id="container"></div>
You haven't called display function anywhere. Along with it, you also should call fetchFollowers with a proper async/await to wait for a response, and then you can use it for data population on HTML.
const url = 'https://api.github.com/users/john-smilga/followers?per_page=100'
const fetchFollowers = async () => {
const response = await fetch(url);
const data = await response.json();
return data;
}
const display = async () => {
//fetch data
const getData = await fetchFollowers();
const place = document.getElementById("container");
let newFollowers = getData.map((item) => {
const {
avatar_url,
login,
html_url
} = item;
return `<article class="card">
<img src="${avatar_url}">
<h4> ${login}</h4>
view profile
</article>`;
})
.join(" ");
place.innerHTML = newFollowers;
}
//call `display` function
display();
<div id="container"></div>
Hi Salman when you are calling fetch followers the function is returning promise and you are trying to iterate over a promise object instead you need to wait for the data to be fetched before iterating over it there are multiple ways to do this adding one of the methods to fix your code.
const url = 'https://api.github.com/users/john-smilga/followers?per_page=100'
const fetchFollowers = async () => {
const response = await fetch(url);
const data = await response.json();
return data;
}
const display = async () => {
const getData = await fetchFollowers();
console.log(getData);
const place = document.getElementById("container")
let newFollowers = getData.map((item)=> {
const { avatar_url, login, html_url } = item;
return `<article class="card">
<img src="${avatar_url}">
<h4> ${login}</h4>
view profile
</article>` ;
})
.join(" ");
place.innerHTML =newFollowers;
}
display();
You can update the above code as per your needs. Hope you understand the underlying problem.
that line:
const getData =fetchFollowers();
return a promise, but not a result from a promise
wrap all code in async function and:
const getData = await fetchFollowers();
use kind of promise syntax:
fetchFollowers().then(getData=>{console.log(getData); ...other code...});

How to show loader during multiple api calls in a loop in React

I have two API's
First API returns list of items which I am iterating to get each item's detailed data.
Here's the code
const [loader, setLoader] = useState(false);
React.useEffect(() => {
const fetchUsers = async() => {
setLoader(true);
const users = await getUsers();
const promises = users.map(async (user) => {
let userData = await getUsersDetailedData(user.userId);
return userData
});
let finalUsers = await Promise.all(promises);
setLoader(false);
}
fetchUsers();
}, [])
I am updating loader state before the api call and after call but it is not working.
Loader state is updating these many times and loader is not displaying
logs
Try it in this way,
React.useEffect(() => {
const fetchUsers = async() => {
const users = await getUsers();
const promises = users.map(async (user) => {
let userData = await getUsersDetailedData(user.userId);
return userData
});
let finalUsers = Promise.all(promises);
return finalUsers;
}
setLoader(true);
fetchUsers().then(res=>{
setLoader(false);
});
}, [])

How to escape this callback hell

I'm currently trying to fetch data from public API about a country and its neighboring countries to render on my html.
renderCountry( ) is a function to implement on my html with the data I will receive.
I also excluded some unnecessary codes, which I believe is not major in this particular case.
This is how I fetch data:
const getCountryAndNeighbour = function(country) {
fetch(`https://restcountries.com/v2/name/${country}`)
.then(response => response.json())
.then(data => {
renderCountry(data[0]);
const neighbour = data[0].borders;
neighbour.forEach(country => {
fetch(`https://restcountries.com/v2/alpha/${country}`)
.then(response => response.json())
.then(data => renderCountry(data, `neighbour`))
});
})
}
Here, you will see callback hell architecture. Any idea for escape from that?
Thanks in advance.
You can try using async/await. You would add async before the function keyword and add await as needed. See below to see this in action:
const getCountryAndNeighbour = async function (country) {
const res = await fetch(`https://restcountries.com/v2/name/${country}`)
const data = await res.json();
renderCountry(data[0]);
const neighbour = data[0].borders;
await Promise.all(
neighbour.map(async country => {
let response = await fetch(`https://restcountries.com/v2/alpha/${country}`)
response = await response.json();
return renderCountry(response, 'neighbour');
});
);
}
You can rewrite it using async/await
eg.
const getCountryAndNeighbour = async country => {
const response = await fetch(`https://restcountries.com/v2/name/${country}`);
const data = await response.json();
renderCountry(data[0]);
const neighbour = data[0].borders;
neighbour.forEach(async country => {
const response = await fetch(`https://restcountries.com/v2/alpha/${country}`)
const data = await response.json();
renderCountry(data, `neighbour`);
});
};
Please note that forEach will run all promises in the same time.
If you want to run one by one you should use eg. for loop or some util like Bluebird.map which allows you to specify a concurrency
Good luck!
This will do using Async/await
async function getCountryData(country) {
const response = await fetch(`https://restcountries.com/v2/name/${country}`);
return await response.json();
}
async function getNeighbourData(country) {
const response = await fetch(`https://restcountries.com/v2/alpha/${country}`);
return await response.json();
}
async function getCountryAndNeighbour(country) {
const data = await getCountryData(country);
const neighbourCountries = data[1].borders;
for (const neighbour of neighbourCountries) {
const response = await getNeighbourData(neighbour);
console.log(response);
}
}
Add the necessary validations when checking [0]/[1] in your function.

How to return values from the Object Promise in Jquery

I am trying to return the values from the object of Promises, the values are printed in the console but when I am displaying it on the HTML, it is showing "OBJECT PROMISE" in place of the returned Value.
My code is
const priceConversion = async(data) =>{
const url = 'http://www.geoplugin.net/json.gp?'
const response = await fetch (url)
const resJSON = await response.json()
const val = resJSON['geoplugin_currencySymbol'] + Math.round(data * resJSON['geoplugin_currencyConverter'])
return val
}
The type of val returned is String here. but as soon as it is called from an object, it gives the above mentioned output, i.e "Object Promise"
The code for the Object is
let price = {
basic:{
monthly: priceConversion(0),
annual:priceConversion(0)
},
standard:{
monthly:priceConversion(9),
annual:priceConversion(4.5),
},
premium:{
monthly:priceConversion(17),
annual:priceConversion(7)
}
}
For Document manipulation, I am using the following method
let monthly = true
if (monthly === true){
$("#freeMonthly").empty().text(`${price.basic.monthly}`)
$("#standardMonthly").empty().text(`${price.standard.monthly}`)
$("#premiumMonthly").empty().text(`${price.premium.monthly}`)
}
It would be really great if anyone could help with this one as I couldn't find any solution that could resolve this issue.
Thank You!
Try to wrap everything in an async function and use await every time you call your function:
const priceConversion = async(data) => {
const url = 'http://www.geoplugin.net/json.gp?'
const response = await fetch(url)
const resJSON = await response.json()
const val = resJSON['geoplugin_currencySymbol'] + Math.round(data * resJSON['geoplugin_currencyConverter'])
return val
}
const calculatePrice = async() => {
return {
basic: {
monthly: await priceConversion(0),
annual: await priceConversion(0)
},
standard: {
monthly: await priceConversion(9),
annual: await priceConversion(4.5),
},
premium: {
monthly: await priceConversion(17),
annual: await priceConversion(7)
}
}
}
const main = async() => {
try {
console.log("In the main")
const price = await calculatePrice()
let monthly = true
if (monthly === true) {
$("#freeMonthly").empty().text(`${price.basic.monthly}`)
$("#standardMonthly").empty().text(`${price.standard.monthly}`)
$("#premiumMonthly").empty().text(`${price.premium.monthly}`)
}
} catch (err) {
console.log(err)
}
}
main()
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div id="freeMonthly">freeMonthly</div>
<div id="standardMonthly">standardMonthly</div>
<div id="premiumMonthly">premiumMonthly</div>
</body>
</html>

How to merge asynchronous function's callback result

Here is the code to get some information about server.
cpu.usage()
.then(info => {
console.log(info);
});
cpu.free()
.then(info => {
console.log(info)
});
mem.info()
.then(info => {
console.log(info)
});
I want to get every result in a function.
get_resource () {
...
console.log(cpu_usage, cpu_free, mem_info);
};
How can I design it?
Thank you.
You can try to use async/await to do that:
var get_resource = async function () {
var cpu_usage = await cpu.usage();
var cpu_free = await cpu.free();
var mem_info = await mem.info();
console.log(cpu_usage, cpu_free, mem_info);
};
Or
Promise.all([cpu.usage(), cpu.free(), mem.info()]).then(function (info) {
console.log('cpu_usage:', info[0]);
console.log('cpu_free:', info[1]);
console.log('mem_info:', info[2]);
})
You can use Promise.all() as following:
let cpuUsage = cpu.usage()
let cpuFree = cpu.free()
let memInfo = mem.info()
Promise.all([cpuUsage, cpuFree, memInfo]).then((values) => {
console.log(values);
});
If you can use ES6, then you can use array destructuring while getting results:
Promise.all([cpuUsage, cpuFree, memInfo]).then(([cpuUsageResult, cpuFreeResult, memInfoResult]) => {
console.log(cpuUsageResult);
console.log(cpuFreeResult);
console.log(memInfoResult);
});
Callback Hell
This is the old scenario where you would have to call things inside one another
cpu.usage()
.then(cpu_usage => {
cpu.free()
.then(cpu_free => {
mem.info()
.then(mem_info => {
console.log(cpu_usage, cpu_free, mem_info);
});
});
});
Async Await
in this scenario you make a function that is asynchronous.
async function get_resource () {
const cpu_usage = await cpu.usage();
const cpu_free = await cpu.free();
const mem_info = await mem.info();
console.log(cpu_usage, cpu_free, mem_info);
};
The value assigned to each const in the async function is the same value that you get as an argument in the callback of the then.

Categories