【问题标题】:JavaScript loop output not in correct order - how to fix this?JavaScript 循环输出的顺序不正确 - 如何解决这个问题?
【发布时间】:2016-03-16 02:04:22
【问题描述】:

我编写了一个 JavaScript 循环,它应该获取 8 个 arrays 并将它们以特定顺序存储在 localStorage 中。它可以工作,但是顺序有点混乱:值都“向下移动”localStorage 中的一个键,即最后一个值被放入第一个键,第一个值被放入第二个键,等等。我尝试了for 循环和“自建”循环,它们都给出了相同的结果。这是代码,我将在底部做更多解释。

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

所以基本上,这是一个为我正在为游戏开发的战斗系统获取角色统计数据的函数。 该函数基于角色的id 构建一个参考URL,并将其设置为src 用于同样在函数中创建的script 标记(此标记稍后会被删除并为每个循环重新创建)。 script 标记中使用的每个源文件都是一个 JavaScript 文件,它在 sessionStorage 值中设置角色的统计信息。然后将这些值放入相应的变量中,然后将变量放入数组中并存储在localStorage 中以供以后使用。 现在,正如我之前提到的,除了localStorage 值的顺序之外,这一切都很好。这就是我寻求帮助的地方。

有人可以检查我的代码并提出一个可以修复localStorage 中值顺序的解决方案吗?我可以根据需要发布更多代码/解释。

干杯。

~DM

【问题讨论】:

  • temp.src = referenceurl; 是您真正需要设置&lt;script&gt; 元素的“src”属性的全部内容。
  • 另外:脚本不会立即加载和评估。当您在文档中添加&lt;script&gt; 时,浏览器将在运行完您发布的代码后处理脚本内容;它们不会中断当前的执行线程。
  • 寻求更多说明。你的意思是stats 数组有问题吗?或者你的意思是当它们应该在fighter1_stats中时,它们被保存在键fighter2_stats
  • @Pointy - 谢谢,我没想到。我将尝试 Ted A. 的答案,看看我是否可以让它发挥作用。 =)
  • @TedA。 - 是的,我的意思是这些值存储在错误的键中。

标签: javascript html local-storage session-storage


【解决方案1】:

正如 Pointy 提到的,您的问题是在运行 localStorage 代码之前,代码不会暂停以等待下载并执行获取的脚本。这意味着该脚本第一次运行时, sessionStorage 值将为空,第一个循环将为空,第二个循环将具有来自第一个脚本的值,依此类推。当您第二次运行脚本时,上次运行的最后一个值在 sessionStorage 中,因此第一个键获取最后一个值,等等。

您可以通过 (1) 使用脚本标签的 onload 事件和 (2) 使用闭包来冻结脚本的 i 状态(因为它会随着循环的继续而改变)来解决这个问题。

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

【讨论】:

  • 您好 Ted A.,感谢您的回答。我尝试运行您的代码,但是 getClosure 函数没有执行。我要试验一下,看看能不能让它工作。 =)
  • 好消息 - 我让它工作了。我所要做的就是将onLoad 更改为onload(没有大写“L”)。谢谢你的帮助!!
  • 啊。很好的捕捉,在答案中固定。无法执行代码,因为那里有太多实现特定的东西(发布未执行的代码不好,我知道!)很高兴它有帮助。
猜你喜欢
  • 1970-01-01
  • 2019-02-23
  • 1970-01-01
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-27
相关资源
最近更新 更多