함수 실행 조건에 '시간' 요소 추가하기

setTimeout()

setTimeout(function[, delay, arg1, arg2, ...]);
  • function
    • 타이머가 만료 된 후 실행할 함수이름.

  • delay
    • function을 실행하기 전에 기다릴 시간.(ms)

  • arg1, ..., argN
    • function에 전달할 추가 매개변수.

반환 값

timeoutID

  • 자료형: 양의 정수.

  • setTimeout() 함수가 생성한 타이머를 식별할 때 사용.

    이 값을 clearTimeout()에 전달하면 타이머를 취소할 수 있다.

    같은 객체에서 반복하여 호출하는 setTimeout() 또는 setInterval()메서드는 절대로 같은 timeoutID를 사용하지 않는다.

    다른 객체끼리는 다른 timeoutID 풀을 사용한다.

  • 어떤 함수를 주기적으로 반복하여 호출해야 할 필요가 있을 때는 setInterval()을 사용한다.

비동기 함수

setTimeout()은 비동기 함수이다.
함수 스택의 다른 함수 호출을 막지 않는다.

setTimeout(() => {console.log("5초 후에 나올 메세지")}, 5000);
setTimeout(() => {console.log("3초 후에 나올 메세지")}, 3000);
setTimeout(() => {console.log("1초 후에 나올 메세지")}, 1000);

// (1초 경과 후) 1초 후에 나올 메세지
// (3초 경과 후)3초 후에 나올 메세지
// (5초 경과 후)5초 후에 나올 메세지

각각 따로 실행된다는 것이다.
첫 번째 함수가 실행되기 위한 5초가 경과하는 동안 다른 함수들도 동시에 실행되기 시작한다.
각자의 시간 조건이 만족될 때 각자의 내용이 실행된다.

함수의 실행이 완료된 후 다른 함수를 호출하는 구조를 원한다면 promise를 사용해야 한다.


This 관련 이슈

setTimeout()에서 이 메서드를 지정할 경우 내부의 this값이 예상치와 다를 수 있음에 유의한다.

저 자세한 사항은 mdn web docs 참조


이를 바탕으로 모달창에 카운트 다운 기능을 구현해보았다.

    <!-- 화면 전체를 어둡게 만들어주는 background-->
    <div class="background" id="background">
        <!-- 모달 팝업을 감싸주는(?) window-->
        <div class="window">
            <!-- 모달의 실제 내용을 표시하는 popup-->
            <div class="popup"></div>
        </div>
    </div>

모달도 몸통은 있어야 한다.
html로 틀을 만들어주고 css로 꾸민다.

.background {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100vh;
            background-color: rgba(0, 0, 0, 0.3);
            /* z-index는 모달을 화면의 맨 앞으로 끌어내기 위함 */
            /* z-index: 1000; */

            /* 일단 숨겨놓기 */
            z-index: -1;
            opacity: 0;
        }

        /* 모달이 나타날 때 적용할 스타일을 만들기 */
        /* z-index와 opacity를 설정하여 투명도와 위치가 원래대로 나타나도록 */
        .show {
            opacity: 1;
            z-index: 1000;
            transition: all .5s;
        }

        .window {
            /* 배경에 가득 차도록 width와 height 설정 */
            /* 팝업이 들어갈 공간을 제한하기 위해 position: relative 속성 추가 */
            position: relative;
            width: 100%;
            height: 100%;
        }

        .popup {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: #ffffff;
            box-shadow: 0 2px 7px rgba(0, 0, 0, 0.3);

            /* 임시지정? */
            /* 화면의 세로 길이를 넘기는 경우에만 height를 지정하여 스크롤을 넣어둔다 */
            /* 그렇지 않은 경우라면 아래 둘 다 지정하지 않는다 -> 내용을 넣으면 알아서 화면이 늘어나기 때문 */
            width: 200px;
            height: 200px;

            /* 초기에 약간 아래에 배치하여 올라오는 느낌이 들도록 */
            transform: translate(-50%, -40%);
        }

        .show .popup {
            transform: translate(-50%, -50%);
            transition: all .5s;
        }

JavaScript로 모달에 움직임을 넣어준다.

		function modal_open() {
            document.querySelector(".background").className = "background show";
        }

        function modal_close() {
            document.querySelector(".background").className = "background";
        }

        function choosewho() {
            let name = new Array();

            let replace_Char = /[~!@\#$%^&*\()\-=+_'\;<>0-9\/.\`:\"\\,\[\]?|{}]/gi;
            let not_perfect_korean = /[ㄱ-ㅎ ㅏ-ㅣ]/gi;

            for (let i = 1; i < <?php echo $number; ?> + 1; i++) {
                let str = String("insert_name_" + i);
                if (!(document.getElementById(str).value)) {
                    alert(i + "번 타자 대답합니다");
                    return false;
                }
                //테스트를 위한 alert(str);
                name.push(document.getElementById(str));
                //테스트를 위한 alert(name[i - 1]);
            }

            let random_number = Math.floor(Math.random() * name.length);
            let name_picker = name[random_number].value;

            const btn_insert_name_disabled = document.getElementById("btn_insert_name");

            //모달 오픈 직후 제출 버튼 비활성화
            btn_insert_name_disabled.disabled = true;

            //모달 오픈 전 초기값 설정
            $('.popup').html('3')

            //모달 오픈
            modal_open();

            //1초가 지나면 2초가 남음
            setTimeout(function() {
                //getElementsByClassName은 innerHTML 속성을 가지고 있지 않으므로 JQuery사용
                $('.popup').html('2')
            }, 1000);

            //2초가 지나면 1초가 남음
            setTimeout(function() {
                //getElementsByClassName은 innerHTML 속성을 가지고 있지 않으므로 JQuery사용
                $('.popup').html('1')
            }, 2000);

            //3초 경과 시 결과 오픈
            setTimeout(function() {
                $('.popup').html("< " + name_picker + " >" + "\n바로 니가 주인공이야")
                //alert("< " + name_picker + " >" + "\n바로 니가 주인공이야");
            }, 3000);

            //3초+@ 경과 시 모달 외부 클릭으로 모달을 닫을 수 있게
            setTimeout(function() {
                background.addEventListener("click", e => {
                    modal_close();
                }, {
                    once: true
                });
            }, 3030);

            //모달 기능 종료 후 재츌 버튼 활성화
            btn_insert_name_disabled.disabled = false;
        }

setTimeout()의 파라미터에 once: true를 사용하여 호출 할 때마다 해당 함수가 한 번만 실행되도록 하는 것이 포인트였다.

once: true를 넣지 않을 경우, 최초 버튼 이벤트가 실행된 이후에 modal_close()함수가 종료되지 않고 지속된다.

모달 카운트 다운이 끝나고 나서 모달 외부를 클릭하여 모달을 닫을 수 있게 해야하므로 once: true를 사용했다.

엉성하지만 페이지가 굴러가는 중.


놀이 웹
현재 버전 1.93
https://choose-who.herokuapp.com/index.php

0개의 댓글