[JS] setTimeout / setInterval

javaScript 기초를 탄탄하게 다져보자

Posted by lim.Chuck on December 23, 2024

[JavaScript]

기초

  1. [JS] Js기초
  2. [JS] Js기초 변수
  3. [JS] Js기초 자료형
  4. [JS] Js기초 형변환
  5. [JS] Js기초 연산자
  6. [JS] Js기초 반복문
  7. [JS] Js기초 switch
  8. [JS] Js기초 function
  9. [JS] Js기초 객체
  10. [JS] Js기초 배열

중급

  1. [JS] Js중급 호이스팅(Hoisting)과 TDZ(Temporal Dead Zone)
  2. [JS] Js중급 생성자함수
  3. [JS] 객체 메소드(Object methods), 계산된 프로퍼티(Computed property)
  4. [JS] 심볼(Symbol)
  5. [JS] WeakMap WeakSet
  6. [JS] 숫자, 수학 method (Number, Math)
  7. [JS] 문자열 메소드(String methods)
  8. [JS] 배열 메소드(Array methods)
  9. [JS] 구조 분해 할당 (Destructuring assignment)
  10. [JS] 매개변수 리스트와 전개 문법(Rest parameters and spread syntax)
  11. [JS] 클로저(Closure)
  12. [JS] setTimeout / setInterval
  13. [JS] call / apply / bind
  14. [JS] 상속, 프로토타입(Prototype)
  15. [JS] 클래스(Class)
  16. [JS] 클로미스(Promise)
  17. [JS] 비동기 처리(Async/Await)
  18. [JS] Generator
  19. [JS] 메모리 릭(Memory Leak)

setTimeout과 setInterval! 비동기 작업을 처리하는 타이머 함수들이야! ⏰

1. setTimeout 기본

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 기본 사용법
setTimeout(() => {
  console.log("3초 후 실행!");
}, 3000); // 3000ms = 3초

// clearTimeout으로 취소
const timerId = setTimeout(() => {
  console.log("이 메시지는 보이지 않을 거예요!");
}, 1000);

clearTimeout(timerId); // 타이머 취소

// 매개변수 전달
setTimeout(
  (name, age) => {
    console.log(`${name}님은 ${age}살입니다.`);
  },
  2000,
  "김코딩",
  20
);

2. setInterval 기본

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 기본 사용법
setInterval(() => {
  console.log("1초마다 실행!");
}, 1000);

// clearInterval로 중지
const countDown = (count) => {
  const intervalId = setInterval(() => {
    console.log(count);
    count--;

    if (count < 0) {
      clearInterval(intervalId);
      console.log("카운트다운 종료!");
    }
  }, 1000);
};

countDown(5); // 5, 4, 3, 2, 1, "카운트다운 종료!"

3. 실전 활용 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class Timer {
  constructor() {
    this.timers = new Map();
  }

  // 일정 시간 후 한 번 실행
  runLater(name, delay, callback) {
    const timerId = setTimeout(() => {
      callback();
      this.timers.delete(name);
    }, delay);

    this.timers.set(name, timerId);
  }

  // 주기적으로 실행
  runInterval(name, interval, callback) {
    const timerId = setInterval(callback, interval);
    this.timers.set(name, timerId);
  }

  // 특정 타이머 중지
  stop(name) {
    if (this.timers.has(name)) {
      clearTimeout(this.timers.get(name));
      clearInterval(this.timers.get(name));
      this.timers.delete(name);
      return true;
    }
    return false;
  }

  // 모든 타이머 중지
  stopAll() {
    this.timers.forEach((timerId) => {
      clearTimeout(timerId);
      clearInterval(timerId);
    });
    this.timers.clear();
  }
}

// 사용 예시
const timer = new Timer();

// setTimeout 예제
timer.runLater("greeting", 2000, () => {
  console.log("안녕하세요!");
});

// setInterval 예제
timer.runInterval("counter", 1000, () => {
  console.log("매초 실행!");
});

// 3초 후 특정 타이머 중지
setTimeout(() => {
  timer.stop("counter");
  console.log("카운터 중지!");
}, 3000);

4. 애니메이션 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Animator {
  static animate(element, property, start, end, duration) {
    const startTime = performance.now();
    const change = end - start;

    function update(currentTime) {
      const elapsed = currentTime - startTime;
      const progress = Math.min(elapsed / duration, 1);

      // 현재 값 계산
      const current = start + change * progress;
      element.style[property] = `${current}px`;

      // 애니메이션 계속
      if (progress < 1) {
        requestAnimationFrame(update);
      }
    }

    requestAnimationFrame(update);
  }

  static fadeIn(element, duration = 1000) {
    element.style.opacity = "0";
    element.style.display = "block";

    const startTime = performance.now();

    function update(currentTime) {
      const elapsed = currentTime - startTime;
      const progress = Math.min(elapsed / duration, 1);

      element.style.opacity = progress;

      if (progress < 1) {
        requestAnimationFrame(update);
      }
    }

    requestAnimationFrame(update);
  }
}

// 사용 예시
const box = document.querySelector(".box");
Animator.animate(box, "left", 0, 300, 1000); // 왼쪽으로 300px 이동
Animator.fadeIn(box, 2000); // 2초동안 페이드인

5. 디바운스와 쓰로틀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class EventController {
  // 디바운스: 마지막 호출 후 일정 시간이 지나면 실행
  static debounce(func, delay) {
    let timeoutId;

    return function (...args) {
      clearTimeout(timeoutId);

      timeoutId = setTimeout(() => {
        func.apply(this, args);
      }, delay);
    };
  }

  // 쓰로틀: 일정 시간 간격으로만 실행
  static throttle(func, limit) {
    let inThrottle;

    return function (...args) {
      if (!inThrottle) {
        func.apply(this, args);
        inThrottle = true;

        setTimeout(() => {
          inThrottle = false;
        }, limit);
      }
    };
  }
}

// 사용 예시
const handleSearch = EventController.debounce((text) => {
  console.log(`검색어: ${text}`);
}, 500);

const handleScroll = EventController.throttle(() => {
  console.log("스크롤 이벤트 처리");
}, 1000);

// 이벤트 리스너에 적용
input.addEventListener("input", (e) => handleSearch(e.target.value));
window.addEventListener("scroll", handleScroll);

꿀팁! 🍯

  1. 성능 최적화
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// BAD: 중첩된 setTimeout
setTimeout(() => {
  setTimeout(() => {
    setTimeout(() => {
      console.log("콜백 지옥!");
    }, 1000);
  }, 1000);
}, 1000);

// GOOD: Promise 사용
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function betterWay() {
  await delay(1000);
  console.log("1초 후");
  await delay(1000);
  console.log("2초 후");
  await delay(1000);
  console.log("3초 후");
}
  1. 메모리 누수 방지
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class TimerManager {
  constructor() {
    this.timers = new Set();
  }

  setTimeout(callback, delay) {
    const timerId = setTimeout(() => {
      callback();
      this.timers.delete(timerId);
    }, delay);

    this.timers.add(timerId);
    return timerId;
  }

  clearAll() {
    this.timers.forEach(clearTimeout);
    this.timers.clear();
  }
}

// 컴포넌트 언마운트 시
timerManager.clearAll();

이제 타이머 함수들은 마스터! 😎 비동기 작업과 애니메이션을 자유자재로 다룰 수 있을 거야!