简体   繁体   English

javascript在while循环中使用setInterval不起作用

[英]javascript Using setInterval inside a while loop doesn't work

I'm developing a mini game where you have to click on the right target.我正在开发一个小游戏,你必须点击正确的目标。 I have a set of div with different id's numbered from 1 to 9. Every 3 seconds the target changes.我有一组不同 id 的 div,编号从 1 到 9。每 3 秒目标就会改变一次。 To select the target I've done a function that randomly selects a targets until the user hits the correct one.为了选择目标,我做了一个随机选择目标的函数,直到用户击中正确的目标。 This is the code I have made far now:这是我现在所做的代码:

let game;
let victory = false;
let target;


const win = () => {
    victory = true;
    return alert('Has ganado');
}


const setTarget = () => {

    console.log("funcion setTarget");
    target = Math.floor(Math.random() * 9) + 1;

    // Añadimos la classe red
    document.getElementById(target).classList.add("target");

    // Al target actual le ponemos un eventlistener
    document.getElementById(target).addEventListener('click', win);

    return target;

}



// Al target anterior hay que eliminarle la classe red y quitarle el eventlistener
const removeTarget = () => {


    // Eliminamos la classe red
    document.getElementById(target).classList.remove("target");

    // Al target anterior le borro la classe "target"
    document.getElementById(target).removeEventListener('click', win);

    return target;

}


const startGame = () => {


    while (victory) {

        console.log("Entramos en el while");

        setTarget(); // Aplicamos estilo al target y le aplicamos event listener

        setTimeout(() => removeTarget, 30000); // Esperamos 3 segundos y eliminamos el target

    }

    return true;

}



// Ejecuta la función que hace todo el juego
startGame();

Inside the function startGame I need to execute the function setTarget() and then wait 3 seconds before execute removeTarget this should be happening until the user hits the correct element.在函数 startGame 中,我需要执行函数 setTarget() 然后等待 3 秒再执行 removeTarget 这应该发生,直到用户点击正确的元素。 When the users click the correct element the victory changes to true and the loops exits.当用户单击正确的元素时,胜利将变为真并且循环退出。 Now when I load the page it doesnt waits at all and it's going so fast that I can't see the div's changing the color.现在,当我加载页面时,它根本不需要等待,而且速度如此之快,以至于我看不到 div 的颜色变化。

This is the html for if can be usefull:这是 if 的 html 可能有用:

<html>
    <head>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <div>
            <div id="1"></div>
            <div id="2"></div>
            <div id="3"></div>
          </div>
           
          <div>
            <div id="4"></div>
            <div id="5"></div>
            <div id="6"></div>
          </div>
           
          <div>
            <div id="7"></div>
            <div id="8"></div>
            <div id="9"></div>
          </div>


        <script src="script.js"></script>
    </body>
</html>

And the CSS:和 CSS:

div>div {
    width: 100px;
    height: 100px;
    border: 1px solid red;
    display: inline-block;
    border-radius: 50px;
  }
 
  .target {
    background-color: red;
  }

Code Changes:代码更改:

Don't use a while , that is what the interval is for:不要使用while ,这就是间隔的用途:

const startGame = () => {
    setTarget();
    window.my_interval = setInterval(adjustTarget, 30*1000);
}

And then once the user wins, clear the interval:然后一旦用户获胜,清除间隔:

const win = () => {
    clearInterval(window.my_interval);
    removeTarget();
    alert('Has ganado');
}

You'll need an interim method that resets the target.您将需要一个重置目标的临时方法。 So declare another function that does this for you, like:因此,声明另一个为您执行此操作的函数,例如:

function adjustTarget(){
    removeTarget();
    setTarget();
}

Summary of things to learn:学习内容总结:

  • First : victory is false so your while loop never enters.第一victoryfalse所以你的while循环永远不会进入。
  • Second : even if victory were true, you'd lock-up your runtime and get Maximum call stack size exceeded .第二:即使victory是真的,你也会锁定你的运行时并得到Maximum call stack size exceeded The while loop does't wait on the setTimeout() so it would set thousands/millions/billions of timeouts. while循环不会在setTimeout()上等待,因此它会设置数千/数百万/数十亿的超时。
  • Third : You don't need to declare an anonymous function that then return the reference to removeTarget .第三:您不需要声明一个匿名函数,然后返回对removeTarget的引用。 Just pass the removeTarget function reference into setTimeout() directly.只需将removeTarget函数引用直接传递给setTimeout()即可。
  • Fourth : Your starting value for victory at the time you invoke startGame() will always be false .第四:在您调用startGame()时您的victory startGame()将始终为false So you don't need to check it when you start the game.所以你在开始游戏时不需要检查它。
  • Fifth : Consider placing all your code inside a class for easier variable, state, and scope management.第五:考虑将所有代码放在一个class ,以便于变量、状态和范围管理。
  • Sixth : You don't even need a variable for victory , it's implied when a user clicks the 'winning' target.第六:你甚至不需要victory的变量,当用户点击“获胜”目标时它是隐含的。
  • Seventh : You're not using the return values of any of your methods.第七:您没有使用任何方法的return值。 Thus, you shouldn't even use a return statement.因此,您甚至不应该使用 return 语句。

Look at this, I have updated the few lines in JavaScript, rest remains the same看这个,我更新了几行JavaScript,其余保持不变

const win = () => {
victory = true;
clearInterval(startit);
return alert('Has ganado');
}

const startGame = () => {
    console.log("Entramos en el while");
    removeTarget(); // Esperamos 3 segundos y eliminamos el target
    setTarget(); // Aplicamos estilo al target y le aplicamos event listener
}

var startit = setInterval(startGame, 3000);
enter code here

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM