🤹🏻‍♀️ Javascript

제로초 자바스크립트 7장 (가위바위보)

ji-hyun 2021. 10. 24. 21:23
let 아이디 = setInterval(함수, 밀리초);
clearInterval(아이디);

 

setInterval 함수는 사실 반환값이 있다. 반환값은 타이머에 대한 아이디(숫자)로, 나중에 이 값을 사용해 타이머를 제거할 수 있다. 이와 마찬가지로 setTimeout 함수도 clearTimeout 함수로 취소할 수 있다.

 

 

 

 

/* 타이머 멈췄다가 다시 실행하기 */
let intervalid = setInterval(computerHandImg, 50);

const clickButton = () => {
    clearInterval(intervalid);
    // 점수 계산 및 화면 표시
    setTimeout(() => {
        intervalid = setInterval(computerHandImg, 50);
    }, 1000);

}

$scissors.addEventListener('click', clickButton);
$rock.addEventListener('click', clickButton);
$paper.addEventListener('click', clickButton);

 

그림이 멈춘 동안 버튼을 여러번 클릭하고 버튼을 또 클릭하면 일시정지 되지않는 현상이 나타난다.

이런 버그가 나타나게 되는 이유는.. 버튼을 클릭할 때마다

clearInterval 은 interval 만 제거할 수 있다. 따라서 버튼을 누른 횟수만큼 setTimeout 은 여러번 호출되고 각각 1초 뒤에 setInterval 을 하게 되어 그림이 매우 빠른 속도로 돌아가게 된다.

 

 

위의 코드의 자세한 작동 순서는

1. clickButton 5번 호출: 인터벌 1번, 2번, 3번, 4번, 5번(얘만 intervalid) (덮어쓰임 현상)

2. 그 다음 1초 뒤에 버튼을 클릭하면 5번만 취소

 

 

 

 

해결방법 1

removeEventListener 메서드를 사용한다.

 

 

 

 

 

클릭 이벤트를 제거했다고 생각했다면 큰 오산이다.

fun(1) === fun(1) 은 false 의 결괏값이 나온다. 객체부분에서 공부했었다. (객체 사이의 비교 연산은 false이다.)

 

 

 

이렇게 b가 a를 참조할 수 있어야 지워지는 것이다.

정말 많이 하는 실수이므로 기억해두자.

 

 

 

 

 

해결방법 2

플래그 변수를 이용한다.

 

플래그변수: 참거짓이냐에 따라서 안에 코드를 실행해줄지 말지를 결정하는 변수

 

let intervalid = setInterval(computerHandImg, 50);

let clickable = true;
const clickButton = () => {
    if (clickable) {
        clearInterval(intervalid);
        clickable = false;
        setTimeout(() => {
            clickable = true;
            intervalid = setInterval(computerHandImg, 50);
        }, 1000);
    }
}

$scissors.addEventListener('click', clickButton);
$rock.addEventListener('click', clickButton);
$paper.addEventListener('click', clickButton);

 

 

 

 

 

 

 


 

유튜브 댓글 참고

 

clickButton을 5번 호출하면 인터벌이 쌓이고 다시 버튼 호출했을 때 마지막 인터벌만 사라진다고 하셨는데 setTimeout은 clear를 안해줬지만 setTimeout에 실행되는 인터벌은 아이디를 변수에 저장해뒀고, 다시 버튼을 눌렀을 땐 인터벌은 해제되어야 하는 것 아닌가요? 예를 들어 1번 인터벌 실행 중 1번 버튼 누름->1번인터벌취소->setTimeout의 새로운 2번인터벌실행->2번 버튼 누름->2번인터벌취소 이런 식으로 버튼을 누르면 상쇄가 되는 것 같아서요. setTimeout은 인터벌을 실행시키는 거고 이게 clear되지 않는다고 해서 인터벌이 취소되지 않는다는 게 무슨 말인지를 모르겠습니다ㅠㅠ

 

연달아 누를 때입니다. 연달아누르는 경우는 setTimeout 내부는 클릭보다 나중에 실행되는 것이라 아이디가 대입되는 것도 나중입니다.

 

연달아 누를 경우 setInterval이 1초 뒤 실행되기 때문에 버튼을 눌렀을 때 실행되는 clearInterval은 지울 인터벌이 없다.