본문 바로가기
개발서적/모던 자바스크립트 Deep Dive

프로미스 (모던 자바스크립트 Deep Dive)

by 사과넹 2024. 4. 17.
반응형

 

  • ES6에서 비동기 처리를 위한 새로운 패턴 프로미스 제시!

45.1 비동기 처리를 위한 콜백 패턴의 단점

콜백 헬

비동기 함수는 동기처리 되는 함수들이 모두 처리되고 나서 마지막에 처리되기 때문에 비동기로 동작하는 코드에서 나오는 결과를 외부로 반환하거나 상위 스코프의 변수에 할당하면 기대한 대로 동작하지 않는다.

  • 동기 함수가 자바스크립트 엔진의 콜 스택에서 모두 처리되어야, 비동기 함수가 태스크 큐에서 꺼내어져 실행이 완료될 수 있다.
    • 비동기 함수는 브라우저 또는 Nodejs에서 이벤트 루프와 태스크 큐에서 따로 관리되기 때문에 그렇다.
  • 그러므로 비동기 함수 내부의 코드를 외부로 반환하거나 상위 스코프에서 할당하면 눈으로 보는 것처럼 동작하지 않을 수 있다.

위와 같은 문제로, 비동기 함수의 처리 결과에 대한 후속 처리는 비동기 함수 내부에서 이루어져야 한다.

  • 주로 사용되는 것이 콜백 함수이다.
    • 성공 콜백 함수와 실패 콜백 함수
  • 하지만… 비동기 함수의 결과를 후속 처리를 비동기 함수가 하고, 또 그 후속 처리를 비동기 함수가 하고 .. 이런 현상이 반복된다면? → 콜백 헬 발생! 중첩 함수의 가독성 저하!

 

콜백 함수의 에러 처리

  • 아래의 예시에서 setTimeout에 뱉은 error를 catch에서 잡지 못한다.
    • setTimeout은 비동기 함수이므로 콜백 함수를 기다리지 않고, 이미 콜 스택에서 제거된다.
    • 이후 콜스택에 setTimeout은 없을거고, setTimeout의 콜백 함수가 실행되지만 …
    • 에러는 호출자 방향으로 전파되기 때문에, 호출자가 없는 콜백 함수의 에러는 catch에서 잡지 못한다.
      • 콜 스택 아래 방향
try {
	setTimeout(() => { throw new Error('Error!'); }, 1000);
} catch (e) {
	console.error('에러', e);
}

 

45.2 프로미스의 생성

  • ECMAScript의 표준 빌트인 객체
  • 비동기 처리를 할 콜백 함수를 인수로 전달 받는다. (= executor 함수 )
  • resolve와 reject 함수를 인수로 전달 받는다.
const promise = new Promise((resolve, reject) => {
	if (success) {
		resolve('result');
	} else {
		reject('fail');
	}
});
  • 프로미스 상태 정보
    • pending : 비동기 처리가 아직 수행되지 않은 상태
    • fulfilled : 비동기 처리가 수행된 상태(성공), settled 상태
      • PromiseValue에 resolve의 결과 값
    • rejected : 비동기 처리가 수행된 상태(실패), settled 상태
      • PromiseValue에 Error 객체의 값

 

45.3 프로미스의 후속 처리 메서드

  • then(resolve시 실행 함수, reject시 실행 함수)
  • catch(reject시 실행 함수)
  • finally(결과와 상관없이 무조건 1번 실행 함수)

then에서 하는 일과 catch에서 하는 일 이 겹쳐보이는 것은 착각이 아니다.

  • 사실상 catch도 reslove시 실행 함수를 내부적으로 받긴 한다. undefined로..
    • 요런식으로.. catch(undefined, reject 실행 함수)
  • 하지만 결론은, then은 resolve시 콜백 함수, catch는 reject시 콜백 함수만 사용하자.
    • 가독성이 좋다는 장점만 있는 것이 아니다.
    • then의 reject 콜백함수는 then의 reslove 함수의 에러까지는 처리 못한단다..

 

45.5 프로미스 체이닝

  • 콜백 헬을 탈출하여 프로미스 체이닝을 사용하자
  • then → then → catch 체이닝이 가능하다.
  • 가독성이 얼마나 좋은가.

 

45.6 프로미스의 정적 메서드

Promise.resolve, Promise.reject

  • 이미 존재하는 값을 래핑하여 프로미스를 생성하기 위해 사용

 

Prmoise.all

  • 여러 개의 비동기 처리를 병렬 처리할 때 사용
  • 모든 프로미스의 fulfilled 상태를 기다린다.

 

Promise.race

  • all과 동일하게 이터러블을 인수로 받는다.
  • 먼저 fulfilled상태가 된 프로미스를 resolve 한다.

 

Promise.allSettled

  • fulfilled 상태가 아닌 settled 상태가 되면 결과를 반환한다.

 

45.7 마이크로태스크 큐

  • 프로미스 후속 처리 메서드의 콜백 함수는 마이크로태스크 큐에 저장된다.
    • 일반 비동기 함수는 태스크 큐에 저장된다.
  • 마이크로태스크 큐는 태스크 큐보다 우선순위가 높다.
  • 실행 순서: 콜 스택 → 마이크로태스크 큐 → 태스크 큐

 

45.8 fetch

  • HTTP 요청 전송 기능과 프로미스를 지원하는 Web API
  • response 객체를 래핑한 Promise 객체를 반환한다.
    • response.json()을 통해 역직렬화해야 사용 가능하다.
  • 네트워크 장애나 CORS 에러만 프로미스를 reject하기 때문에 에러 처리를 명시적으로 해야 한다.
  • axios는 모든 에러를 catch에서 처리한다.
728x90
반응형