【问题标题】:Why isn't clearInterval() stopping the setInterval function?为什么 clearInterval() 不停止 setInterval 函数?
【发布时间】:2020-03-13 03:05:13
【问题描述】:

我正在制作一个蛇游戏,整个游戏在 runGame() 函数内运行。我将函数设置为每 80 毫秒重复一次,就像这样 startGame = setInterval(runGame, 80) 然后在 runGame() 函数内部检查是否存在冲突。在checkForCollision() 函数中,我设置了一个超时以在 5 秒后返回 true,表明发生了冲突,然后运行代码 clearInterval(runGame) 这什么都不做?这是为什么呢?

//grab the canvas/set its context/create the snake and its size
const cvs = document.querySelector('canvas');
const ctx = cvs.getContext('2d');
const unit = 16;
const snake = [
    {
    //set the snakes starting position in the middle of the canvas
    x: cvs.width/2 - 8,
    y: cvs.height/2 - 8
    }
];
let food = {x: 0, y: 0}

let startGame = setInterval(rungame, 80);
getFood();

let direction;
function rungame() {
    isRunning = true;
    draw(snake[0].x, snake[0].y, "limegreen");

    document.addEventListener('keydown', (event) => {
        if(event.keyCode == 37) direction = "left";
        else if(event.keyCode == 38) direction = "up";
        else if(event.keyCode == 39) direction = "right";
        else if(event.keyCode == 40) direction = "down";
    });

    
    
    
    switch(direction) {
        case "left":
            draw(snake[0].x, snake[0].y, "#858585");
            snake[0].x -= unit
            draw(snake[0].x, snake[0].y, "limegreen");
            break;
        case "right":
            draw(snake[0].x, snake[0].y, "#858585");
            snake[0].x += unit
            draw(snake[0].x, snake[0].y, "limegreen");
            break;
        case "up":
            draw(snake[0].x, snake[0].y, "#858585");
            snake[0].y -= unit
            draw(snake[0].x, snake[0].y, "limegreen");
            break;
        case "down":
            draw(snake[0].x, snake[0].y, "#858585");
            snake[0].y += unit
            draw(snake[0].x, snake[0].y, "limegreen");
            break;         
    }

    if(checkForCollision()) clearInterval(startGame);
}

//--------------------HELPER FUNCTIONS
function draw(x, y, color) {
    for(let i = 0; i < snake.length; i++) {
        ctx.fillStyle = color;
        ctx.fillRect(x, y, unit, unit, color);
    }
}

function getFood() {
    let x = Math.floor(Math.random() * cvs.width/unit) * unit;
    let y = Math.floor(Math.random() * cvs.height/unit) * unit;
    food.x = x;
    food.y = y;
    draw(food.x, food.y, 'red');
}

function checkForCollision() {
    setTimeout(function() {
        return true;
    }, 5000)
}
html, body {
    margin: 0;
    padding: 0;
}

body {
    font-family: 'Odibee Sans';
    height: 100vh;
    display: flex;
    justify-content: center;
    background-color: #333;
}

.wrapper {
    display: flex;
    flex-direction: column;
    justify-content: center;
    position: relative;
    top: -27.5px;
}

canvas {
    background-color: #858585;
}

.score {
    width: 50px;
    height: 50px;
    align-self: center;
    color: white;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 4rem;
    padding-bottom: 5px;
    text-shadow:  5px 0px 0px #858585;
    /* why does align self work here but not justify-content */
}
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Snake 2.0</title>  
    <link href="https://fonts.googleapis.com/css?family=Odibee+Sans&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="wrapper">
        <div class="score">0</div>
        <div class="canvas-wrap">
            <canvas width="1008" height="528"></canvas>
        </div>
    </div>
</body>
<script src="script.js"></script>
</html>

【问题讨论】:

  • 因为checkForCollision 本身不返回true。回调函数返回 true。目前它返回undefined,这被认为是虚假的

标签: javascript


【解决方案1】:

那是因为你的 checkForCollision 函数返回 undefined 所以条件永远不会是 true,你只是在计时器内执行函数并且返回值永远不会传递给要返回的外部函数。

【讨论】:

    【解决方案2】:

    您不能从async 函数返回,setTimeout 是一个异步函数。 checkForCollision 函数将始终返回 undefined

    解决方案:

    checkForCollision 函数返回一个promise

    function checkForCollision() {
      return new Promise((resolve, reject) => {
        setTimeout(function() {
          resolve(true);
      }, 5000)
      });
    }
    

    并等待承诺得到解决。

    (async function() {
      let  collision = await checkForCollision();
      if(collision);
        clearInterval(startGame);
    })();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多