JS-10 (22/11/10)

nazzzo·2022년 11월 13일
0

1. setTimeout & setInterval



window.setTimeout()

(setTimeout은 window 객체에 내장된 메서드)


1, (1초 뒤에) 2,(1초 뒤에) 3....을 출력하려면

문법

window.setTimeout(callback, 1000)
window.setInterval(callback, 1000)
  • callback: function (실행할 함수)
  • 1000 : number (시간. 1000ms(1초))
  • window.은 생략 가능. (자바스크립트 스펙이 아니다. '브라우저'가 제공하는 함수)

console.log("hello world")
setTimeout (function (){
    console.log(1)
}, 5000)

// > 5초 뒤에 1 출력 (한번만)


setInterval(function(){
    console.log(2)
}, 1000)

// > 1초마다 2 출력 (반복해서)
  • setTimeout
    2번째 인자값인 number, 즉 밀리세컨드가 충족되면 딱 '한 번만' 실행

  • setInterval
    2번째 인자값인 number, 즉 밀리세컨드가 충족될 때마다 '반복'해서 실행


↓ setTimeout을 이용해서 1, 2, 3 순으로 출력하는데 2를 1초만 늦게 출력하고 싶다면

console.log(1)
setTimeout (function (){
    console.log(2)
}, 1000)
console.log(3)

의도한 바와 달리 1 > 3 > 2 순으로 출력된다.

이 이유를 이해하려면 먼저 몇가지 개념에 대해 알아야 하는데...

싱글 스레드

비유하자면 프로그램을 해석하는 사람이 한 명. 자바스크립트 또한 싱글스레드로 구동된다. (콜스택이 하나)

백그라운드와 테스트큐

브라우저는 콜스택 외에 '백그라운드'라는 여분의 공간을 만들어 두었다.
자바스크립트는 setTimeout()은 브라우저가 처리할 코드라고 판단(윈도우(브라우저) 내장 함수)하고 해당 코드의 처리를 백그라운드로 넘긴다.
이 때 console.log(1)과 console.log(3)은 자바스크립트가 처리해서 출력.

백그라운드로 넘어간 코드 중에서 익명함수에 해당하는 부분은 설정한 지연시간이 지나면(1000) '테스트 큐' 라는 공간으로 이동한다.
테스트큐에 담긴 함수는 콜스택이 비는 즉시 콜스택으로 이동. (이 과정을 '이벤트 루프'라고 한다.)
그래서 1 > 3 > 2 순으로 출력된 것.

이벤트 루프(!)

이벤트 발생시 호출되는 콜백함수들을 태스트 큐에 전달하고 태스트 큐에 담겨있는 콜백함수들은 콜스택으로 넘기는 과정.

콜스택과 백그라운드는 모두 코드를 해석하는 공간이지만 (일종의 멀티 스레드)
콜스택은 '동기', 백그라운드는 '비동기' 방식으로 코드가 처리된다.

동기 & 비동기

  • 동기 ~ 진행중인 작업이 완전히 끝나야만 다음 작업 진행
  • 비동기 ~ 선행 작업 진행 중에도 다른 작업 병행 가능.
    (setTimeout은 비동기 코드. 그러므로 백그라운드로 넘어간 지연코드들은 동시에 시간이 돌아간다.)

비동기 코드를 동기 형태로 짜 맞추는 것(순서 맞추기)은 쉽지 않다. (코드가 백그라운드로 넘어가는 순간 사용자가 컨트롤할 수 없기 때문. 사용자가 다룰 수 있는 공간은 콜스택 뿐)


예제)
a. 세탁기 돌리기 10초
b. 빨래 널기 5초
c. 정육점 다녀오기 30초
가장 효율적인 순서는 a > c > b이다.

setTimeout(function(){
    console.log("세탁기")
}, 10 * 1000)

setTimeout(function(){
    console.log("빨래 널기")
}, 5 * 1000)

setTimeout(function(){
    console.log ("정육점")
}, 30 * 1000)

빨래 > 세탁기 완료 > 정육점 순으로 출력된다.

해결방법은 콜백함수를 다중으로 실행하는 것.

setTimeout(function(){
    console.log("세탁기")

    setTimeout(function(){
        console.log("빨래 널기")
    }, 5 * 1000)
}, 10 * 1000)

setTimeout(function(){
    console.log ("정육점")
}, 30 * 1000)
console.log("시작")
setTimeout(function (){
    console.log("세탁기 가동")
    setTimeout(function (){
        console.log("세탁기 종료")
        setTimeout(function (){
            console.log("빨래 널기")
            console.log("끝")
        })
    }, 5000)

    setTimeout(function (){
        console.log("정육점")
    }, 3000)
}, 1000)

시작 > (1초) 세탁기 가동 > (4초(1+3)) 소고기 사오기 > (6초(1+5)) 세탁기 종료 > 빨래 널기 > 끝
(callback hell을 유발한다)

정리

console.log(1)
setTimeout(function (){
    console.log(2)
}, 0)
console.log(3)

1 > 3 > 2. 1과 3이 콜스택을 먼저 빠져나가고 setTimeout은 백그라운드 > 테스트큐 > 콜스택

아래는 자주 범하는 실수

let name
setTimeout(function () {
    name = "joo"
}, 0)

console.log(name)

→ undefined 출력. (name을 아직 할당하기 전에 호출한 것)
백그라운드는 컨트롤할 수 없다. (전역변수에서 선언과 할당을 미리 끝마쳐야 함)

+)

let num = 0
const timeId = setInterval(function () {
    console.log(++num)
    if (num === 5) clearInterval(timeId)
}, 1000)

clearInterval() ~ 인터벌을 빠져나가기 위해 사용하는 메서드. (빠져나가려는 코드에 미리 변수명을 설정)

++)

setTimeout(function (name){
    console.log(name)}, 1000
	,"joo" 

1초 뒤 name의 인자값으로 들어간다. (알아는 두자)

0개의 댓글

관련 채용 정보