1. 탐구

Mission

1. delay함수 만들기

  1. while문 활용

    function delay(ms) {
      const start = Date.now();
      while (Date.now() - start < ms) {
      }
    }
    
    console.log(1);
    
    delay(1000);
    
    console.log(2)
    

    while문을 활용하여 물리적으로 시간이 흐르도록 했다. while문은 비동기적으로 실행되지 않고, call stack에서 처리가 되기 때문이다.

  2. Promise + setTimeout 활용

    //
    
    function delay(ms) {
      return new Promise((resolve) => setTimeout(resolve, ms));
    }
    
    (
      async function () {
        console.log(1);
        await delay(1000);
        console.log(2)
      }
    )()
    
    

    Promise객체를 생성하여, callback함수로 setTimeout을 넣어주었다.

2. n초마다 함수 실행하는 함수 만들기

let interval = setInterval(() => {
  console.log(num);
}, 500)

3. Promise 객체들을 만들고, 모든 Promise 객체가 resolve되었을 때, 다음 문장을 실행하기

const promiseMaker = (ms) => new Promise(resolve => setTimeout(() => {
  console.log(ms)
  resolve()
}, ms)); // Promise 객체 생성기

const promise1 = promiseMaker(1000); // 1초의 setTimeout Promise객체를 리턴하는 Promise 객체
const promise2 = promiseMaker(2000);

(
  async function () {
    console.log(1)
    await Promise.all([promise1, promise2]); // Promise.all은 Promise객체를 배열로 전달받아 병렬로 처리한다.
    console.log(2)
  }
)()

출력 : 1, 1초 후 1000, 2초 후 2000과 2

다양한 상황

  1. setTimeout

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

    1, 3이 먼저 출력되고, 1초 후에 2가 출력된다. 2는 node.js api에 넘어가, 비동기적으로 처리가 되고, callback queue에 넘겨지기 때문이다.

  2. setInterval로 일정 간격으로 실행하고, 중단하기

    const num1 = numberMaker();
    let interval;
    
    startButton.addEventListener('click', () => {
      interval = setInterval(() => {
        num1.addNumber();
        console.log(num1.getNumber());
      }, 500)
    })
    
    stopButton.addEventListener('click', () => {
      clearInterval(interval)
    })
    
    
  3. Promise 생성기

    const promiseMaker = second => () => new Promise((resolve) => setTimeout(resolve, 1000 * second))
    
    const promise1 = promiseMaker(1); // promiseMaker는 Promise 객체를 반환한다.
    const promise2 = promiseMaker(2);
    
    (
      async function () {
        console.log(1);
        await promise1();
        console.log(2);
        await promise1();
        console.log(3);
      }
    )()
    
    
    const promise1 = new Promise(resolve => setTimeout(resolve, 1000));
    
    (
      async function () {
        console.log(1);
        await promise1;
        console.log(2);
        await promise1;
        console.log(3);
      }
    )()
    
    

    위를 실행하면 1이 출력되고, 1초 후 2와 3이 함께 출력된다.

    하지만 아래와 같이 함수로 Promise 객체를 생성하면 1 > 2 > 3이 순차적으로 실행이 된다.

    const promise1 = () => new Promise(resolve => setTimeout(resolve, 1000));
    
    (
      async function () {
        console.log(1);
        await promise1();
        console.log(2);
        await promise1();
        console.log(3);
      }
    )()
    

    왜냐하면, 첫 번째 코드에서 promise1은 하나의 객체이기 때문이다. Promise객체를 생성하고, 처음 await promise에서 해당 Promise의 setTimeout이 실행된다. 그 이후에 다시 await되면, 이미 resolve된 상태이므로 추가적인 대기 시간 없이 실행된다.

    하지만 두 번째 코드에서는 promise1()을 실행했을 때 해당 Promise객체가 생성이 된다. Promise객체 앞에 await키워드가 있으므로, 끝날 때까지 기다렸다가 순차적으로 처리가 된다.

2. 고민