JS & TS/JavaScript

[JavaScript] 동기(Synchronous), 비동기(Asynchronous), Promise

Bay Im 2024. 2. 13. 16:35
  • 동기와 비동기 뜻
    • 동기란 특정한 작업이 종료된 후 다음 줄의 작업을 실행하는 것
    • 비동기란 특정한 작업을 종료되기 까지 기다리지 않고 실행되는 것
    • JS에서 대부분 작업들은 자동적으로 비동기적으로 실행되는 부분이 많다.
  • 동기(Synchronous) vs 비동기(Asynchronous)
    • Synchronous
      • 한번에 하나의 함수만 실행, 실행되는 동안 blocking → Single Thread in Single Process
      • Runtime → Execution Context → Execution Context Stack → Lexical Enviroment
    • Asynchronous
      • 한번에 하나의 함수만 실행
      • 특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행
      • I/O를 수행하는 비동기 함수는 Background에 넘긴다. (non-blocking) → Single Thread But Multi Process
      • Runtime → Execution Context → Callstack → Background → OS → Task Queue → CallStack
    • CallStack (호출 스택)
      • 실행되는 함수가 등록되는 Stack
    • TaskQueue
      • 실행되어야 할 콜백 함수가 대기하는 Queue
    • Event Loop
      • TaskQueue에 있는 함수를 차례로 Callstack 으로 이동
    • Background
      • 별도 Process로 I/O 처리 후 콜백함수를 TaskQueue로 이동
  • 전통적인 비동기 Callback Pattern
    • JavaScript Asynchronous Programming History
      • Callback
      • Promise
      • Generator
      • Async / Await
  • Promise - ES6 표준 Built-in 객체(function)
    • Callback pattern의 단점을 극복하기 위해 출현
    • 안전하고 유지보수가 쉬운 코드 작성 가능 (exception safe)
    • 호출 시 Promise instance 반환 후 resolve & reject
    • Promise instance를 전달할 수 있어 편리
      • const p = new Promise(resolveFn, rejectFn){};
    • Promise 객체는 성공(fulfiled) 또는 실패(rejected) 상태를 갖는다.
      • try {
          setTimeout(() => {
            console.log(new Date());
            throw new Error('어디로?');
          }, 1000);
        } catch(err) {
          console.error('잡히나?', err);
        }​
    • Promise - basic pattern
      • const promi = new Promise((resolve, reject) => {
          setTimeout(() => {
            const now = Date.now();
            if (now % 2 === 0) resolve(console.log('fulfill', now));
            else reject(new Error('어디로?'));
          }, 1000);
        });
        
        console.log(promi);
        
        promi.then(
          succ => console.log('Resolve!'),
          fail => console.log('Reject!', fail)
        );
  • Promise Class Methods
    • Promise.resolve
      • 이미 존재하는 값
      • Promise.resolve(x).then(val ⇒ console.log(val));
      • new Promise(resolve ⇒ resolve(x)).then(console.log);
    • Promise.reject
      • Promise.reject(new Error(’…’)).catch(console.error);
      • new Promise((_, reject) ⇒ reject(new Error(’…’))).catch(console.error);
  • Promise Class Methods (Cont’d)
    • Promise.all
      • 여러 Promise Fn을 동시실행(concurrency)
      • 모두 성공(fulfilled) 시 시간과 무관하게 순서 보장
      • 하나라도 실패(rejected) 시 바로 catch로
      • Promise.all(iterables).then().catch(…
      • new Promise.all([p1, p2]).then(arr ⇒ console.log(arr));
    • Promise.race
      • 여러 Promise Fn 중 가장 빠른 것 하나만
      • 하나라도 실패(rejected) 시 바로 catch로
      • Promise.race(iterables).then().catch(..
      • new Promise.race([p1, p2]).then(arr ⇒ console.log(arr));
    • Promise.any
      • 여러 Promise Fn 중 제일 빨리 성공한 하나
      • 하나라도 성공(resolve) 시 바로 then으로
      • Promise.any(iterables).then().catch(…
      • new Promise.any([p1, p2]).then(…
    • Promise.allSettled
      • 여러 Promise Fn이 성공이건 실패건 모두 settled 될 때
      • 순서 보장
      • Promise.allSettled(iterables).then().catch(…
      • new Promise.allSettled([p1, p2]).then(…
  • async 함수
    • async / wait
      • Promise를 생성하고 소비하기 위한 문법적 설탕
      • 비동기 함수에서 콜백을 사용하는 대신 단순한 논리적 흐름(sync 동기처럼, 직렬)을 완성
      • Promise의 then, catch, finally를 사용할 필요 없음
      • async는 Promise를 반환, await는 resolve, reject와 매핑
      • 예외(erro)는 거부(reject)고, 거부(reject)는 예외(throw)다.
      • 반환(성공)은 확정(resolve)이고, 완료(resolve)는 결과(result)다.
      • ES2020부터는 최상위 수준 await 사용가능
  • async 함수의 병렬 처리
    • only Promise & then
      • 각각이 별도(OS) thread로 실행되므로 병렬이다.
    • async / await
      • 차례로 단일 thread가 실행되므로 직렬이다.
      • 연관이 없는 비동기 함수 실행에 async/await을 남발하지 말기
  • 비정상 await
    • map에서의 실수
      • 각각이 별도 Promise(thread)로 실행 (async는 Promise를 반환한다.)
    • filter에서의 실수
      • 각각이 Promise(thread) 반환 (never false)
  • fetch 함수
    • fetch()는 첫번째 인자로 URL, 두번째 인자로 옵션 객체를 받고 Promise 타입의 객체 반환
      • 옵션 객체: method, headers, body
    • 반환된 객체는 API 호출이 성공했을 경우에는 응답(response) 객체를 resolve하고 실패했을 경우에는 예외(erro) 객체를 reject
      • 응답 객체: status, headers, body
    fetch(url, options)
      .then((response) => console.log("response:", response))
      .catch((error) => console.log("error:", error));
    

 

728x90