Reputation: 73
As someone who is still very new to JS i am struggling to understand why some of the functions and code i write give inconsistent outputs inside the console. For example the output of an array will contain 4 items on one refresh of the webpage, then contain 8 items on the next refresh. Why might this happen?
Example of this:
function biggestChanges(idsList) {
var listOfChanges = []
for (let i = 0; i < 16; i++) {
fetch(`jsonFiles\\${idsList[i]}.json`)
.then(response => response.json())
.then(data => {
//get data from JSON file
var priceCurrentNEW = data.JSONdata[data.JSONdata.length - 1].prices[0]
var priceDayBeforeNEW = data.JSONdata[data.JSONdata.length - 2].prices[0]
var priceCurrentUSED = data.JSONdata[data.JSONdata.length - 1].prices[1]
var priceDayBeforeUSED = data.JSONdata[data.JSONdata.length - 2].prices[1]
var changeNEW = priceCurrentNEW / priceDayBeforeNEW * 100 -100
var changeUSED = priceCurrentUSED / priceDayBeforeUSED * 100 - 100
var averageChange = (changeNEW + changeUSED) / 2
averageChange = averageChange.toFixed(2)
subList = [idsList[i], averageChange]
listOfChanges.push(subList)
//run on last iteration.
if (i == 15) {
var orderedList = []
var originalLength = listOfChanges.length
for (var x = 0; x < 16; x++) {
var max = listOfChanges[0][1]
var index = 0
// -k on range as on each iteration the length of the list decreases by 1
for (var k = 0; k < 16-k; k++) {
if (listOfChanges[k][1] > max) {
max = listOfChanges[k][1]
index = k
}
}
orderedList.push(listOfChanges[index])
listOfChanges.splice(index, 1)
}
console.log(orderedList, "orderedlist")
for (var l = 0; l < orderedList.length; l++){
document.getElementById(`change-${orderedList[l][0]}`).innerHTML = "change: £" + orderedList[l][1]
}
}
})
}
}
function finalBiggestChanges() {
fetch("JSONitemIDsList.json")
.then(response => response.json())
.then(data => {
biggestChanges(data.ids)
})
}
finalBiggestChanges()
Upvotes: 0
Views: 31
Reputation: 665130
You've got a race condition. //run on last iteration.
actually runs during the callback of the last iteration to start the fetch(`jsonFiles\\${idsList[i]}.json`)
call, but not necessarily when the last http response arrived.
You can mitigate this by doing if (listOfChanges.length == 16)
(i.e. when the 16th response was added to the array) instead of if (i == 15)
, but really the proper solution is to use Promise.all
instead:
function loadChange(id) {
return fetch(`jsonFiles\\${idsList[i]}.json`)
.then(response => response.json())
.then(data => {
//get data from JSON file
var priceCurrentNEW = data.JSONdata[data.JSONdata.length - 1].prices[0]
var priceDayBeforeNEW = data.JSONdata[data.JSONdata.length - 2].prices[0]
var priceCurrentUSED = data.JSONdata[data.JSONdata.length - 1].prices[1]
var priceDayBeforeUSED = data.JSONdata[data.JSONdata.length - 2].prices[1]
var changeNEW = priceCurrentNEW / priceDayBeforeNEW * 100 -100
var changeUSED = priceCurrentUSED / priceDayBeforeUSED * 100 - 100
var averageChange = (changeNEW + changeUSED) / 2
averageChange = averageChange.toFixed(2)
return [id, averageChange]
});
}
function finalBiggestChanges() {
return fetch("JSONitemIDsList.json")
.then(response => response.json())
.then(data => {
return Promise.all(data.ids.slice(0, 16).map(loadChange));
})
.then(listOfChanges => {
listOfChanges.sort((a, b) => b[1] - a[1]); // largest first
console.log(listOfChanges, "orderedlist")
for (const change of listOfChanges) {
document.getElementById(`change-${change[0]}`).innerHTML = "change: £" + change[1]
}
});
}
finalBiggestChanges().catch(console.error);
Upvotes: 1