프론트엔드 개발을 하며 생각보다 많이 비동기 처리를 해야 했고 이전에는 끼워맞추는 식으로 콜백 함수를 집어넣었다. 그러다 아래와 같이 A 작업이 끝나면 B 작업, B 작업이 끝나면 C 작업. 이런 식의 연쇄적인 작업을 구현하기 위해 콜백을 막무가내로 사용하는 콜백 지옥을 경험했다.
const calculate = (callBack: (result: number) => void) => {
const addend = 3;
setTimeout(() => callBack(addend), 1000);
};
const callBack1 = (augend: number, callBack: (result: number) => void) => {
const addend = 2;
setTimeout(() => callBack(augend + addend), 1000);
};
const callBack2 = (augend: number, callBack: (result: number) => void) => {
const addend = 1;
setTimeout(() => callBack(augend + addend), 1000);
};
calculate((result: number) => {
callBack1(result, (result: number) => {
callBack2(result, (result: number) => {
console.log("end of callback : " + result);
});
});
});
프로미스는 비동기 작업의 미래 완료 또는 실패를 나타낸다.
new Promise((resolve, reject) => {
...
resolve();
...
});
.then: 성공했을 때 실행되는 resolve 정의 .catch: 실패했을 때 실행되는 reject 정의doSomething().then((value) => doSomething1(value).then(...위에 콜백지옥을 다뤘는데 프로미스는 이를 Chaining을 통해 해결한다.
Chaining이 가능한 이유는 프로미스의 then에서 프로미스를 넘겨줄 수 있기 때문이다.
const calculate = (): Promise<number> => {
const addend = 3;
return new Promise((resolve) => {
setTimeout(() => {
resolve(addend);
}, 1000);
});
};
const callBack1 = (augend: number): Promise<number> => {
const addend = 2;
return new Promise((resolve) => {
setTimeout(() => {
resolve(augend + addend);
}, 1000);
});
};
const callBack2 = (augend: number): Promise<number> => {
const addend = 1;
return new Promise((resolve) => {
setTimeout(() => {
resolve(augend + addend);
}, 1000);
});
};
calculate()
.then(callBack1)
.then(callBack2)
.then((result) => console.log(result));
그리고 에러 핸들링에 관해서도 간단해졌다. 이전 콜백지옥에서는 모든 비동기처리 함수에 에러 함수를 중복해서 넣었다면 프로미스에서는 catch로 에러를 핸들링 할 수 있다.
...
calculate()
.then(callBack1)
.then(callBack2)
.then((result) => console.log(result))
.catch(failureCallback);
비동기 작업이 성공적으로 마치던 실패로 끝나던 끝으로 실행하는 메서드를 정의한다.
connection을 종료시켜야하는 상황에서 사용할 수 있을 것 같다.
calculate()
.then(callBack1)
.catch(failureCallback);
.finally(() => console.log("The End"));