setInterval
재귀적인 setTimeout
let timerId = setTimeout(function tick() {
alert('tick');
timerId = setTimeout(tick, 2000);
// 현재 실행 끝난 후 2초간 딜레이 후 실행
// 딜레이 시간을 쓰지 않으면 바로 동기적으로 실행함
}, 2000);
setInterval 보다 유연하게 이용가능
ex) 서버에 요청이 너무 많아 딜레이를 늘려야 할 때
let delay = 5000;
let timerId = setTimeout(function request() {
...요청 전송...
if(서버 과부하 때문에 요청이 실패한다면...) {
// 다음 실행까지 인터벌을 좀 늘리자..
delay *= 2;
}
timerId = setTimeout(request, delay);
}, delay);
setInterval이 보장 못하는 실행간 딜레이를 보장
setInterval은 실제로 기재한 시간보다 짧은 딜레이로서 동작
→ 딜레이 시간안에 함수의 동작시간이 포함되기 때문
→ 함수 실행 종료 후에 딜레이가 걸리는게 아닌 단순 시간을 재서 호출을 하게 된다
→ 극단적으로 함수 실행 시간이 길어질 경우 바로 실행될 수도 있다
재귀를 이용한 setTimeout은 함수실행 종료 후 딜레이를 적용하여 호출한다
let i = 0;
let start = Date.now();
function count() {
// 1부터 1000000000 세는 무거운 작업
// cpu 잠깐 멈출 듯함
for (let j = 0; j < 1e9; j++) {
i++;
}
alert("Done in " + (Date.now() - start) + 'ms');
}
count();
// setTimeout으로 스케줄링
let i = 0;
let start = Date.now();
function count() {
// 약간의 무거운 작업을 해봅시다. 1000000 단위로만 센다
do {
i++;
} while (i % 1e6 != 0);
if (i == 1e9) {
alert("Done in " + (Date.now() - start) + 'ms');
} else {
setTimeout(count);
// 호출을 스케쥴링합니다.
// 1000000000에 도달하지 않았다면 다시 동기적으로 실행
}
}
count();
// 이 경우 작업을 setTimeout으로 나누든 안나누든 큰 차이는 없다
// 차이를 만들기 위한 개선 코드
let i = 0;
let start = Date.now();
function count() {
// 스케줄링을 함수의 도입부로 옮김
if ( i < 1e9 - 1e6) {
setTimeout(count); // 함수 종료 후 실행됨
}
do {
i++;
} while (i % 1e6 != 0);
if ( i == 1e9) {
alert("Done in " + (Date.now() - start) + 'ms');
}
}
count();
// 작업전 스케줄링 후 작업 실행시 시간이 적게든다
// 브라우저에 중첩된 타이머 딜레이를 최소화 가능하기 때문
// 브라우저에서는, 중첩된 타이머를 얼마나 자주 동작할 수 있는지에 대한 제한이 있다.
// HTML5 표준은 "5개의 중첩된 타이머 이후에는 간격이 적어도 강제로 4ms 만큼 있을 것입니다."
// 라고 말한다.
// 보통 실행시 1 1 1 1 9 15 24 ... 중첩되는 타이머가 늘어갈수록 점점 딜레이가 늘어간다
// 스케줄링은 어느 부분에 하느냐에 따라서도 딜레이가 달라지게 된다
<div id="progress"></div>
<script>
let i = 0;
function count() {
for (let j = 0; j < 1e6; j++) {
i++;
// 현재의 i 값을 progress div에 넣습니다.
// innerHTML에 대해 더 알아봅시다.
progress.innerHTML = i; // 다 i 작업 끝난후에 html에 반영된다
}
}
count();
</script>
// setTimeout 적용
<div id="progress"></div>
<script>
let i = 0;
function count() {
// do a piece of the heavy job (*)
do {
i++;
progress.innerHTML = i;
} while (i % 1e3 != 0);
if (i < 1e9) {
setTimeout(count); // 순차적으로 html에 계속 반영
}
}
count();
</script>
자바스크립트는 어떻게 작동하는가: 이벤트 루프와 비동기 프로그래밍의 부상, async/await을 이용한 코딩 팁 다섯 가지
자바스크립트 개발자라면 알아야 할 33가지 개념 #10 스케쥴링: setTimeout 과 setInterval