JS 函数在控制台中给出不一致的输出

JS functions giving inconsistent outputs in console

作为一个对 JS 还很陌生的人,我很难理解为什么我编写的一些函数和代码在控制台中给出了不一致的输出。例如,一个数组的输出将在一次网页刷新时包含 4 个项目,然后在下一次刷新时包含 8 个项目。为什么会发生这种情况?

示例:

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

您遇到了竞争条件。 //run on last iteration. 实际上在 start fetch(`jsonFiles\${idsList[i]}.json`) 调用的最后一次迭代回调期间运行,但不一定在最后一个 http 响应到达时运行。

您可以通过 if (listOfChanges.length == 16)(即第 16 个响应添加到数组时)而不是 if (i == 15) 来缓解这种情况,但真正正确的解决方案是使用 Promise.all :

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