ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] 비동기 프로그래밍(promise, async/await)
    JavaScript 2024. 7. 11. 10:18
    728x90

    promise, async/await으로 비동기를 처리하는 예제를 통해 자바스크립트가 비동기를 처리하는 과정을 살펴보겠습니다.

    const findUserById = (userId) => {
      console.log('findUserById 함수 호출');
    
      return new Promise((resolve, reject) => {
        console.log('findUserById 함수가 반환하는 promise 객체');
        if (userId === 1) {
          resolve('유저를 찾았습니다.');
        } else {
          reject(new Error(`userId가 ${userId}인 유저를 찾을 수 없습니다.`));
        }
      });
    };
    
    async function getUser() {
      console.log('In function!');
    
      setTimeout(() => {
        console.log('promise 호출 전 setTimeout 호출');
      }, 1000);
    
      console.log('유저 찾는 함수를 호출하기 전');
    
      const userId = 1;
      const res = await findUserById(userId);
      console.log('유저 찾는 함수를 호출한 후');
    
      setTimeout(() => {
        console.log('promise 호출 후 setTimeout 호출');
      }, 500);
    
      console.log('res', res);
    }
    
    console.log('Before function!');
    getUser();
    console.log('After function!');

     

    1. 먼저 전역 실행 컨텍스트를 생성되고 콜 스택에 푸시됩니다. 전역 코드가 실행되면 'Before function!'이 출력되고 getUser 함수가 호출됩니다.

     

    2. getUser함수가 호출되어 함수 실행 컨텍스트를 생성합니다. 'In function'을 출력하고 setTimeout을 만나 setTimeOut 실행 컨텍스트를 생성합니다.

     

    3. setTimeOut 함수 실행되면서 setTimeout 실행 컨텍스트가 생성되고 콜 스택에 push됩니다.콜백 함수를 호출 스케줄링하고 종료되어 setTimeout 실행 컨텍스트가 콜 스택에서 pop됩니다.

     

    4. JS엔진이 수행하는 1-3번과 아래의 과정과 동시에 4번 과정은 브라우저에서 진행하는데 먼저,webAPI에 콜백함수를 추가합니다. 타이머는 setTimeout에 전달한 두 번째 인자 1000ms 동안 실행됩니다. 타이머가 종료되면 태스크 큐로 이동합니다. 현재는 브라우저에서 전달받은 1000ms만큼 타이머가 실행되고 있습니다.

     

    5. 브라우저에서 수행하는 4번과 동시에 진행되고  JS엔진이 수행하고 있습니다. getUser 함수를 계속 실행하는데, '유저 찾는 함수를 호출하기 전'을 출력합니다. 이후 await 키워드를 엔진이 만나서 getUser 함수가 일시정지되고, getUser 실행 컨택스트가 콜스택에서 pop됩니다. finduserbyId 함수가 호출되어 실행 컨텍스트가 만들어지고 콜 스택에 추가됩니다. 'findUserById 함수 호출'을 출력합니다.

     

    6. finduserbyId 함수는 Promise를 반환하므로 Promise 생성자 함수 실행 컨텍스트가 생성되며 콜스택에 push 됩니다. 성공 시 resolve 된 Promise가 반환되고 resolve 함수가 마이크로태스크 큐에 추가됩니다. Promise 생성자 함수가 종료되고 Promise 생성자 실행 컨텍스트가 콜 스택에서 pop 됩니다.

    마이크로태스크 큐에는 프로미스의 후속 처리 메서드의 콜백 함수가 일시적으로 저장됩니다. 태스크 큐보다 우선순위가 높아 이벤트 루프는 마이크로태스크 큐에 대기하고 있는 함수를 먼저 실행합니다.

     

    7. findUserById 함수에서 더 이상 실행할 코드가 없으므로 findUserById 함수 실행이 종료되고 findUserById 실행 컨텍스트가 콜 스택에서 pop 됩니다.

     

    8. 남은 전역 코드를 실행해서 'After function!'을 출력합니다. 실행할 전역 코드가 없으므로 전역 실행 컨텍스트가 콜스택에서 pop됩니다.

     

    9. 마이크로태스크 큐의 resolve 된 함수가 이벤트 루프에 의해 콜스택으로 이동됩니다. 그리고 getUser 함수 실행 컨텍스트가 재생성 후 콜스택에 push 됩니다.

     

    10. getUser 함수가 5번에서 일시 정지 된 부분부터 다시 실행합니다. '유저 찾는 함수를 호출한 후'을 출력하고, 자바스크립트 엔진이 setTimeout 메서드를 만납니다.  setTimeout 실행 컨텍스트가 생성되어 콜 스택에 push됩니다.

     

    11. setTimeout 함수가 실행되고 콜백함수가 호출 스케일링하고 종료되어 setTimeout 실행 컨텍스트가 콜 스택에서 pop 됩니다.

     

    12. 브라우저에서 동시에 진행합니다. 먼저, webAPI에 콜백함수를 추가합니다. 타이머는 setTimeout에 전달한 두 번째 인자 500ms 동안 실행됩니다. 타이머가 종료되면 태스크 큐로 이동합니다. 현재는 브라우저에서 전달받은 500ms만큼 타이머가 실행되고 있습니다.

     

    13. resolve 된 promise의 result 값을 출력하고 getUser 함수에서 더이상 실행할 코드가 없으므로 함수가 종료되고 getUser 실행 컨텍스트가 콜 스택에서 pop됩니다.

     

    14. 브라우저가 자바스크립트 엔진과 동시에 수행하고 있던 타이머 실행에서 500ms 타이머 설정된 콜백함수가 먼저 종료되어 테스크 큐에 push됩니다. 1000ms 타이머가 설정된 콜백함수가 그 다음으로 종료되어 테스크 큐에 푸시됩니다.

     

    15. 이벤트루프는 콜 스택에 비어있음을 확인하고 마이크로태스크 큐도 비어있으므로 태스크 큐를 확인합니다. 큐는 선입선출이므로 콜백함수 1이 먼저 콜 스택에 push 됩니다. 실행 후 콜백함수 1은 콜 스택에서 pop됩니다.

     

    16. 이벤트루프는 콜 스택에 비어있음을 확인하고 태스크 큐를 확인합니다. 이제 콜백함수 2가 콜 스택에 push 됩니다. 실행 후 콜백함수 2는 콜 스택에서 pop됩니다.

     

    728x90

    'JavaScript' 카테고리의 다른 글

    1장 데이터 타입  (0) 2023.03.27
Designed by Tistory.