아래 예시 코드는 숫자 n을 매개 변수(parameter)로 받아와 5번에 걸쳐 1초마다 1씩 더해서 출력하는 비동기 작업
1. 콜백 함수 (callback)
const increaseAndPrint = (n, callback) => {
setTimeout(() => {
const increased = n + 1;
console.log(increased);
if (callback) {
callback(increased);
}
}, 1000);
}
increaseAndPrint(0, n => {
increaseAndPrint(n, n => {
increaseAndPrint(n, n => {
increaseAndPrint(n, n => {
increaseAndPrint(n, n => {
console.log('The End');
});
});
});
});
});
setTimeout()
은 비동기적 코드를 만들기 위해 사용하는 것 뿐이다.
- 비동기 처리가 많아질수록 코드가 깊어지는 현상을
콜백 지옥(callback hell)
이라고도 한다.
- 이렇게 코드가 깊어지는 것은
프로미스(Promise)
를 사용하여 줄일 수 있다.
2. 프로미스 (Promise)
const increaseAndPrint = (n) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const value = n + 1;
if (value === 5) {
const error = new Error();
error.name = 'The End';
reject(error);
return;
}
console.log(value);
resolve(value);
}, 1000);
});
}
increaseAndPrint(0)
.then(increaseAndPrint)
.then(increaseAndPrint)
.then(increaseAndPrint)
.then(increaseAndPrint)
.then(increaseAndPrint)
.catch(error => {
console.log(error);
});
프로미스(Promise)
를 사용할 때, 실행 함수는 프로미스를 이행(resolve)
또는 거부(reject)
할 수 있다.
프로미스(Promise)
를 이행했을 때는 then()
으로 호출을 정의하고, 거부했을 때는 catch()
로 호출을 정의한다.
거부(reject)
의 상황에서 catch()
를 통해 에러를 출력하기 위해서, new Error()
를 사용하여 에러를 만들었다.
프로미스(Promise)
를 사용함으로써 콜백 함수(callback)
를 사용했을 때 코드가 깊어지던 현상을 극복할 수 있었다.
프로미스(Promise)
의 최대 장점으로는 chaining을 꼽을 수 있다.
- 참고로 단점으로는 에러를 잡을 때 어디에서 에러가 발생했는지 알아내기가 어렵다.
.then(increaseAndPrint)
은 .then(n => { return increaseAndPrint(n) }
을 줄여서 작성한 것이다.