首页 > 解决方案 > 记忆游戏中的setTimeout

问题描述

我正在用我的网页上的 javascript 制作一个记忆游戏。我有 3 个标记为 1、2 和 3 的按钮,它们应该按一定的顺序变成绿色然后再变成白色。顺序是随机的,每回合加1。然后玩家应该以正确的顺序点击按钮。问题是,当我将按钮颜色更改为绿色时,不是每个按钮按正确的顺序变为绿色然后再次变为白色,而是按钮一次全部变为绿色。这是javascript逻辑:

function lightUp() {
  var arrayOrder = gameOrder.split("");
  for(let i = 0; i < arrayOrder.length; i++) {
    document.getElementById("but" + arrayOrder[i]).style.backgroundColor = "green";
    setTimeout(function() {
      document.getElementById("but" + arrayOrder[i]).style.backgroundColor = "white";
    }, 1000);
  }
}

gameOrder是一个数字顺序的字符串(例如“12331232123”)

我认为游戏无法正常工作是因为它的工作方式setTimeout,我相信它会在后台暂停并允许for循环继续运行而不是暂停整个功能一秒钟(这是我想要做的)。

我希望每个按钮在下一个按钮改变颜色之前打开然后关闭。因此,如果顺序是 1 2 3,我希望按钮 1 变为绿色,然后变为白色,然后按钮 2 变为绿色,然后变为白色,最后按钮 3 变为绿色,然后变为白色。

标签: javascript

解决方案


正如 espacarello 所指出的,JS 不是同步的。您可以使函数异步并等待setTimeout.

这是我用 JS “动画”事物的首选方式:

async function lightUp() {
  const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
  for (const i of gameOrder.split('')) {
    const el = document.getElementById(`but${i}`);
    el.style.backgroundColor = 'green';
    await sleep(1000);
    el.style.backgroundColor = 'white';
  }
}

这保持简单和优雅,不会用大量的回调、递归或嵌套setTimeout的 s 弄乱你的代码。它仍然是一个功能。


编辑:重要的是要注意 IE 不支持 Promises 或箭头函数语法。请参阅其他两个答案以获得更广泛的支持。


推荐阅读