Search code examples
javascripthtmllocal-storagesession-storage

JavaScript loop output not in correct order - how to fix this?


I've written a JavaScript loop that is supposed to get 8 arrays and store them in localStorage in a specific order. It works, however the order is a bit messed up: the values are all "shifted down" one key in localStorage, ie the last value is being put into the first key, the first value is being put into the second key, and so on. I have tried both a for loop and a "self-built" loop, which both gave the same results. Here is the code, I will do more explaining at the bottom.

var i = -1;

function getstats() {
    i = i + 1;
    if (i > -1 && i < 9) {
        var ids = document.getElementById("battle_deck_block_" + i).getElementsByTagName("img")[0].id;

        var tribe;
        if (ids < 117603 && ids > 100000) {
            tribe = "Xana";
        } else if (ids < 213403 && ids > 200000) {
            tribe = "Hemi";
        } else {
            tribe = "Theri";
        }

        var referenceurl = "Dot_files/Trade/" + tribe + "/" + ids + ".js";

        var temp = document.createElement("SCRIPT");
        var src = document.createAttribute("src");
        src.value = referenceurl;
        temp.setAttributeNode(src);
        document.head.appendChild(temp);

        var hp = sessionStorage.getItem("minhp");
        var atk = sessionStorage.getItem("minatk");
        var def = sessionStorage.getItem("mindef");
        var wis = sessionStorage.getItem("minwis");
        var agi = sessionStorage.getItem("minagi");

        var stats = [hp, atk, def, wis, agi];

        localStorage.setItem("fighter" + i + "_stats", JSON.stringify(stats));

        document.head.removeChild(temp);

    } else if (i > 8 || i < 0) {
        return;
    };
};
setInterval(getstats, 200);

So basically this is a function that fetches characters' stats for a battle system I am working on for a game. The function builds a reference URL based on the character's id, and sets it as the src for a script tag that is also created in the function (this tag is later deleted and recreated for each loop). Each source file used in the script tag is a JavaScript file that sets the character's stats in sessionStorage values. These values are then put into the respective variable and then the variables are put into an array and stored in localStorage to be used later. Now, as I mentioned earlier this all works fine and dandy, except for the order of the localStorage values. This is where I am looking for help.

Can someone go over my code and come up with a solution that can fix the order of the values in localStorage? I can post more codes/explanations as needed.

Cheers.

~ DM


Solution

  • As Pointy mentioned, your issue is that the code doesn't pause to wait for the fetched script to be downloaded and executed before running the localStorage code. That means the first time this script will run, the sessionStorage values will be empty, the first loop would be empty, the second loop would have the values from the first script, and so on. When you run the script a second time, the last values from the previous run are in sessionStorage, thus the first key gets the last values, etc.

    You can fix this by (1) Using the onload event of the script tag, and (2) using closures to freeze the state of i for your script (since it will be mutated as the loop continued).

    var i = -1;
    
    function getClosure(i, temp) {
        // Inside this closure, the current values of i and temp are preserved.
        return function() {
            var hp = sessionStorage.getItem("minhp");
            var atk = sessionStorage.getItem("minatk");
            var def = sessionStorage.getItem("mindef");
            var wis = sessionStorage.getItem("minwis");
            var agi = sessionStorage.getItem("minagi");
    
            var stats = [hp, atk, def, wis, agi];
    
            localStorage.setItem("fighter" + i + "_stats", JSON.stringify(stats));
    
            document.head.removeChild(temp);
        }
    }
    
    function getstats() {
        i = i + 1;
        if (i > -1 && i < 9) {
            var ids = document.getElementById("battle_deck_block_" + i).getElementsByTagName("img")[0].id;
    
            var tribe;
            if (ids < 117603 && ids > 100000) {
               tribe = "Xana";
            } else if (ids < 213403 && ids > 200000) {
               tribe = "Hemi";
            } else {
               tribe = "Theri";
            }
    
            var referenceurl = "Dot_files/Trade/" + tribe + "/" + ids + ".js";
    
            var temp = document.createElement("SCRIPT");
            var src = document.createAttribute("src");
            src.value = referenceurl;
            temp.setAttributeNode(src);
            // The function returned by getClosure() will be executed after this script loads
            temp.onload = getClosure(i, temp);
            document.head.appendChild(temp);
    
        } else if (i > 8 || i < 0) {
            return;
        };
    };
    setInterval(getstats, 200);