프로미스
자바스크립트는 비동기 처리를 위한 패턴으로 콜백 함수를 사용함
콜백패턴은 가독성이 나쁨, 에러의 예외처리가 곤란, 여러 개의 비동기 처리 로직을 한꺼번에 처리하는 것도 한계가 있다. -> 프로미스 등장
비동기 처리 모델은 요청을 병렬로 처리하여 다른 요청이 블로킹 되지 않는 장점이 있다.
하지만, 비동기 처리를 위해 콜백 패턴을 사용하면 처리 순서를 보장하기 위해 여러개의 콜백함수가 중첩되어 복잡도가 높아지는 콜백 헬이 발생하는 단점
비동기 함수의 처리 결과를 반환하는 경우, 순서가 보장되지 않기 때문에 그 반환 결과를 가지고 후속처리를 할 수 없다.
즉, 비동기 함수의 결과처리는 비동기 함수의 콜백 함수 내에서 처리해야한다. 이러다보면 콜백 헬이 생긴다
try {
setTimeout(() => { throw new Error('Error!'); }, 1000);
} catch (e) {
console.log('에러를 캐치하지 못한다..');
console.log(e);
}
**비동기 함수의 콜백 함수는 해당 이벤트가 발생하면 테스크 큐로 이동한 후 호출 스택이 비어졌을 때, 호출 스택으로 이동되어 실행됨
setTimeout은 비동기 함수이므로 콜백함수가 실행될 때까지 기다리지 않고 즉시 종료되어 호출스택에서 제거 -> 이후 tick이벤트가 발생하면 setTimeout함수의 콜백 함수는 태스크 큐로 이동한 후 호출 스택이 비어졌을 때 호출스택으로 이동되어 실행 -> 이때 setTimeout함수는 이미 호출 스택에서 제거된 상태 = setTimeout함수의 콜백함수를 호출한 것은 setTimeout함수가 아니다라는 것을 의미(setTimeout함수의 콜백 함수의 호출자가 setTimeout함수라면 호출 스택에 setTimeout함수가 존재해야 하기 때문에)
예외는 호출자 방향으로 전파된다. 하지만 setTimeout함수의 콜백함수를 호출한 것은 setTimeout함수가 아니다.
따라서 setTimeout함수의 콜백 함수내에서 발생시킨 에러는 catch블록에서 캐치되지 않아 프로세스가 종료
프로미스의 생성
// Promise 객체의 생성
const promise = new Promise((resolve, reject) => {
// 비동기 작업을 수행한다.
if (/* 비동기 작업 수행 성공 */) {
resolve('result');
}
else { /* 비동기 작업 수행 실패 */
reject('failure reason');
}
});
비동기 처리가 성공하면 콜백함수의 인자로 전달받은 resolve함수를 호출 이때 프로미스 상태는 fulfilled상태
비동기 처리가 실패하면 reject함수를 호출 이때 프로미스는 rejected상태
비동기 함수 내에서 promise객체를 생성하고 내부에서 비동기 처리를 구현
promise의 후속처리 메소드
promise로 구현된 비동기 함수는 promise객체를 반환하여야한다.
promise로 구현된 비동기 함수를 호출하는 측에서는 promise 객체의 후속처리 메소드를 통해 비동기 처리 결과나 에러메세지를 전달받아 처리해야함.
promise 객체는 상태를 갖는다. 이 상태에 따라 후속처리 메소드를 체이닝 방식으로 호출
then 두개의 콜백 함수를 인자로 전달 받음. 첫번째 콜백함수는 성공시 호출, 두번째함수는 실패시 호출
then메소드는 promise를 반환
catch 예외가 발생하면 호출 , 이역시 promise반환
promise.all
프로미스가 담겨 있는 배열 등의 이터러블을 인자로 전달 받는다.
전달 받은 모든 프로미스를 병렬로 처리하고, 처리결과를 반환하는 새로운 프로미스를 반환한다.
Generator
이터러블을 생성하는 함수이다.
이터레이션 프로토콜 준수해 이터러블을 생성하는 방식보다 간편하게 이터러블을 구현할 수 있다. 또한 제너레이터 함수는 비동기 처리에 유용하게 사용된다.
제너레이터 함수는 funtion* 키워드로 선언 , 그리고 하나이상의 yield문을 포함.
// 제너레이터 함수 선언문
function* genDecFunc() {
yield 1;
}
// 제너레이터 메소드
const obj = {
* generatorObjMethod() {
yield 1;
}
};
제너레이터 함수를 호출하면 제너레이터 함수의 코드 블록이 실행되는 것이 아니라 제너레이터 객체를 반환한다