I cannot access the specific objects inside the array. I pushed the data to the array from an api. When i console log countriesArr it shows the full array of objects with all its properties, but when I try to access the specific object in a specific index I get undefined. Also, it should return an array but the typeof shows its an object? Can anyone help?
const countriesURL = 'https://restcountries.eu/rest/v2/all';
let countriesArr = [];
async function getCountriesData() {
const response = await fetch(countriesURL);
const data = await response.json();
showCountries(data);
}
function showCountries(countries) {
countries.forEach((country) => {
countriesArr.push(country)
})}
console.log(countriesArr) //this shows array of objects
console.log(countriesArr[0]) //this shows undefined????
CodePudding user response:
your main problem is async fetching of data, so you make request to the server and while it is making, your next code is compeleting
getCountriesData() is loading...
showCountries(countries) complete!
console.log(countriesArr) complete!
console.log(countriesArr[0]) complete!
In this case countries array is empty and when you take [0] element which is not exists, JS return 'undefined'.
Try to use Promise API to avoid this:
const countriesURL = 'https://restcountries.eu/rest/v2/all';
let countriesArr = [];
async function getCountriesData() {
const response = await fetch(countriesURL);
const data = await response.json();
showCountries(data);
}
function showCountries(countries) {
countries.forEach((country) => {
countriesArr.push(country)
})
}
/* this function return special type Promise */
getCountriesData().then(res => {
console.log(countriesArr)
console.log(countriesArr[0])
})
CodePudding user response:
Try like this:
const countriesURL = 'https://restcountries.eu/rest/v2/all';
let countriesArr = [];
async function getCountriesData() {
const loading = document.createElement("P");
loading.innerText = 'Loading ...'
document.body.appendChild(loading);
await fetch(countriesURL)
.then(response => response.json())
.then(data => countriesArr = data)
loading.remove();
console.log(countriesArr)
console.log(countriesArr[0])
}
getCountriesData()
CodePudding user response:
const countriesURL = 'https://restcountries.eu/rest/v2/all';
let countriesArr = [];
async function getCountriesData() {
const response = await fetch(countriesURL);
const data = await response.json();
showCountries(data);
}
function showCountries(countries) {
countries.forEach((country) => {
countriesArr.push(country)
})}
getCountriesData();
console.log(countriesArr) //this shows array of objects
console.log(countriesArr[0]) //this shows undefined????
JavaScript is single threaded-- whether it's running in your browser or NodeJS. So when the Browser processes your code, it will process top>down and evaluate variables in the starting file and proceed to put all functions in the callstack.
When the Browser Engine comes across an asynchronous function, it takes a reference to that function and puts that function into a callback queue, and if it's a promise(which async is since it's just a wrapper on promises), it gets put into a "job queue"/"microtask queue". Once the asynchronous function emits a complete event, the Browser Engine takes that data and pushes that function alongside its reference into the callstack to be run after all current tasks/functions in the stack are done completing. The function reference contains the line number so the engine knows where to evaluate the function.
So knowing this, when you get to getCountriesData(), this asynchronous function gets popped off the main thread, and put into a separate queue that contains threads dedicated for networking related tasks, and program execution immediately processes and evaluates the following console logs before the getCountriesData() finishes executing.
The only way for you to be sure you're correctly inserting/manipulating the data you received from the getCountriesData() into the countriesArr is if you're doing all the data related tasks within that function itself OR in then() proceeding it.