Home > Software engineering >  JS functions giving inconsistent outputs in console
JS functions giving inconsistent outputs in console

Time:01-05

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()

Example output 1Example output 2

CodePudding user response:

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);
  •  Tags:  
  • Related