Promise 는 ES6 에서 추가되었으며, 자바스크립트의 비동기 작업을 처리하기 위해 사용한다.
</br>
기존의 자바스크립트에서는 비동기 작업을 처리하기 위해 콜백 방식을 사용하고 있었다. 하지만 콜백 방식은 여러 단계의 비동기 작업을 처리하는 경우 콜백에서 콜백을 호출하는 코드가 반복되면서 관리가 복잡해지고, 에러 핸들링이 필요한 경우 각 콜백에서 또 다시 콜백으로 처리를 해주어야 했다.
</br>
Callback
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
doSomething(function (result) {
doSomethingElse(
result,
function (newResult) {
doThirdThing(
newResult,
function (finalResult) {
console.log('Got the final result: ' + finalResult);
},
failureCallback,
);
},
failureCallback,
);
}, failureCallback);
</br>
Promise 는 기존의 콜백 방식에 비해 다음과 같은 이점을 가지고 있다.
</br>
- 코드의 가독성 향상
- 비동기 작업 처리 개선
- 비동기식 로직의 제어 흐름 개선
- 향상된 에러 핸들링
</br>
Promise
1
2
3
4
5
6
7
doSomething()
.then((result) => doSomethingElse(result))
.then((newResult) => doThirdThing(newResult))
.then((finalResult) => {
console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);
</br>
사용 방법
</br>
Promise 객체는 생성자를 이용하여 생성할 수 있으며 resolve, reject 함수를 파라미터로 갖는 executor 함수를 인자로 구현해주어야 한다. 새로운 Promise 객체가 생성되면 그 객체는 대기(pending) 상태가 된다.
</br>
Promise 객체를 생성하는 순간 executor 함수가 실행되기 때문에 Promise 를 사용하는 시점에서 객체를 생성하고 실행하기 위해 함수에서 새로운 Promise 객체를 생성하여 리턴하는 방식이 주로 사용된다.
</br>
1
2
3
4
5
6
7
8
const doSomething = () => {
return new Promise((resolve, reject) => {
//비동기 처리를 위해 setTimeout 함수를 사용
setTimeout(() => {
resolve('success');
}, 0);
});
};
</br>
Promise 내에서 작업의 완료와 거부는 executor 함수의 파라미터인 resolve, reject 함수를 이용한다.
</br>
resolve / then
작업이 성공적으로 완료될 경우 resolve 함수를 호출해주면 되는데, 콜백에서 사용할 데이터를 인자로 넣어줄 수 있다. resolve 함수가 호출되면 이행(fulfilled) 상태가 된다.
</br>
resolve 호출의 콜백은 then 에서 구현한다.
</br>
1
doSomething().then((res) => console.log('Response data : ', res));
</br>
여러 단계로 체이닝이 가능하며 return 된 데이터는 다음 콜백에서 사용할 수 있다.
</br>
1
2
3
4
5
6
doSomething()
.then((result) => doSomethingElse(result))
.then((newResult) => doThirdThing(newResult))
.then((finalResult) => {
console.log(`Got the final result: ${finalResult}`);
});
</br>
reject / catch
</br>
반대로 작업이 어떠한 이유로 실패하는 경우 reject 함수를 호출해주면 되고, 마찬가지로 콜백에서 사용할 데이터를 인자로 넣어줄 수 있다. reject 가 호출되면 거부(rejected) 상태가 된다.
</br>
reject 호출의 콜백은 catch 에서 구현한다.
</br>
1
2
3
doSomething().catch((err) => {
console.error(err);
});
</br>
Error handling
</br>
Promise 의 에러핸들링은 reject 와 마찬가지로 catch 콜백에서 구현하여 사용할 수 있다.
</br>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const doSomthing = () =>
new Promise((resolve, reject) => {
//존재하지 않는 객체의 forEach 함수를 호출하면서 오류가 발생한다.
notExistArray.forEach((element) => console.log(element));
resolve();
});
doSomthing()
.then(() => console.log('Success'))
.catch((err) => {
console.error('Unexpected error occurred\n', err);
});
/*
Unexpected error occurred
ReferenceError: notExistArray is not defined
at ....
*/
</br>
여러개의 콜백 체인을 형성한 경우에도 에러가 발생한 위치와 상관없이 catch 콜백으로 에러 핸들링이 이루어진다.
</br>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const doSomthing = () =>
new Promise((resolve, reject) => {
resolve();
});
doSomthing()
.then(() => console.log('First'))
.then(() => {
throw new Error('Error occurred in second callback');
})
.then(() => console.log('Third'))
.catch((err) => {
console.error('Unexpected error occurred\n', err);
});
/*
First
Unexpected error occurred
Error: Error occurred in second callback
at ...
*/
</br>
참고자료
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Using_promises