Это просто проблема времени. Ваши fetch
вызовы выполняются асинхронно , в то время как оператор console.log(...)
в последней строке вашего фрагмента кода выполняется синхронно . Другими словами, ответ на запросы, выданные fetch
, вернутся после того, как свойства console.log(...)
и свойства description
останутся неопределенными.
Вы можете убедиться в этом, взглянув на код ниже, где оператор console.log(...)
заключен в тайм-аут. Теперь извлеченное описание будет зарегистрировано вместо undefined
.
let locations = [
{
latLng: [33.975561111111,28.555830555556],
name: 'Saint Catherine\'s Monastery',
searchTerm: 'Saint Catherine\'s Monastery',
urlSerchTerm: 'Saint%20Catherine\'s%20Monastery'
},
{
latLng: [29.91667,31.2],
name: 'Bibliotheca Alexandrina',
searchTerm: 'Bibliotheca Alexandrina',
urlSerchTerm: 'Bibliotheca%20Alexandrina'
}
];
async function fetchAsync (site, location) {
// await response of fetch call
let response = await fetch(site);
// only proceed once promise is resolved
let data = await response.json();
// only proceed once second promise is resolved
location.description = data[2][0];
return location.description;
}
// let fetches = [];
for (let i = 0; i < locations.length; i++) {
let site = `https://en.wikipedia.org/w/api.php?action=opensearch&search=${locations[i].urlSerchTerm}&limit=1&namespace=0&format=json&origin=*`;
fetchAsync(site, locations[i])
}
window.setTimeout(() => {console.log(locations);}, 5000);
Вы можете решить эту проблему с помощью Promise.all
, как предложено @JeremyThille. Этот SO ответ объясняет второе использование Promise.all
в случае, если это сбивает с толку.
let locations = [
{
latLng: [33.975561111111,28.555830555556],
name: 'Saint Catherine\'s Monastery',
searchTerm: 'Saint Catherine\'s Monastery',
urlSerchTerm: 'Saint%20Catherine\'s%20Monastery'
},
{
latLng: [29.91667,31.2],
name: 'Bibliotheca Alexandrina',
searchTerm: 'Bibliotheca Alexandrina',
urlSerchTerm: 'Bibliotheca%20Alexandrina'
}
];
const fetchDescription = (location) => fetch(`https://en.wikipedia.org/w/api.php?action=opensearch&search=${location.urlSerchTerm}&limit=1&namespace=0&format=json&origin=*`);
const descriptionRequests = locations.map(fetchDescription);
Promise.all(descriptionRequests)
.then(responses => Promise.all(responses.map(r => r.json())))
.then(descriptions => {
descriptions.forEach((description, index) => { locations[index].description = description[2][0]; });
})
.then(() => {
console.log(locations);
});