- 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
반응형
'개발서적 > 모던 자바스크립트 Deep Dive' 카테고리의 다른 글
제너레이터와 async/await (모던 자바스크립트 Deep Dive) (0) | 2024.04.17 |
---|---|
Ajax (모던 자바스크립트 Deep Dive) (0) | 2024.04.17 |
비동기 프로그래밍 (모던 자바스크립트 Deep Dive) (0) | 2024.04.17 |
브라우저의 렌더링 과정 (모던 자바스크립트 Deep Dive) (1) | 2024.04.17 |
배열 (모던 자바스크립트 Deep Dive) (0) | 2024.04.17 |