지난 포스팅에 이어, 자바스크립트의 비동기처리로 인한 문제점 해결을 도와주는 방법인 Promise
에 대해 공부를 해보도록 하겠습니다.
Promise
는 미래에 성공하거나 실패할만한 값을 가지는 비동기 연산을 돕는 객체입니다. 또한 이 Promise
객체는 "대기", "이행", "실패" 세가지 상태를 갖습니다.
대기 중인 Promise
는 값과 함께 이행이 될 수도 실패 될 수도 있습니다. 이렇게 이행이나 실패 될 경우 Promise
의 then()
메서드로, 실패한 경우 catch()
메서드로 그 값이 전달되게 됩니다.
Promise.resolve(value)
는 결괏값이 value
인 이행 상태 Promise
를 생성하며, Promise.reject(error)
는 결과값이 error
인 거부 상태 Promise
를 생성합니다.
예제를 보면서 다뤄보도록 하겠습니다
const promiseResolve = Promise.resolve('성공')
const promiseReject = Promise.reject('실패')
promiseResolve
.then((resolve) => {
console.log('1회', resolve)
return promiseResolve
})
.then((resolve) => {
console.log('2회', resolve)
return promiseResolve
}).then((resolve) => {
console.log('3회', resolve)
return promiseResolve
})
코드 실행 결과
1회 성공
2회 성공
3회 성공
▹Promise {<fulfilled>: '성공'}
이번에는 2회 째 리턴 값으로 promiseReject
를 넣어보겠습니다.
promiseResolve
.then((resolve) => {
console.log('1회', resolve)
return promiseResolve
})
.then((resolve) => {
console.log('2회', resolve)
return promiseReject
}).then((resolve) => {
console.log('3회', resolve)
return promiseResolve
})
코드 실행 결과
1회 성공
2회 성공
▹Promise {<rejected>: '실패'}
코드 실행 결과 2회까지만 성공을 하고 이후 실패를 하는 것을 확인할 수 있습니다.
그렇다면 마지막으로 reject
리턴시 catch()
메서드를 사용하면 결과 값이 어떻게 출력이 되는지 확인을 해보도록 하겠습니다.
promiseResolve
.then((resolve) => {
console.log('1회', resolve)
return promiseResolve
})
.then((resolve) => {
console.log('2회', resolve)
return promiseReject
})
.catch((reject) => {
console.log('3회', reject)
return promiseResolve
})
코드실행결과
1회 성공
2회 성공
3회 실패
코드 실행 결과 catch()
사용 시 3회까지 잘 실행이 되고 실패가 출력되는 것을 확인할 수 있습니다.
사실, 이번에 다룬 Promise
메서드 Promise.resolve
와 Promise.reject
는 async/await
문법이 생긴 후로 쓸모없어졌기 때문에 근래에는 거의 사용하지 않는 추세이긴 합니다.
async/await
문법은 다음 포스팅에서 공부해보도록 하겠습니다.
콜백을 받는 함수를 프로미스를 반환하는 함수로 바꾸는 것을 '프라미스화(promisification)'라고 합니다. 이렇게 만들어진 프로미스 객체는 콜백함수의 결과에 따라 이행 또는 실패 상태의 프로미스를 반환합니다.
코드를 작성하다보면 프로미스가 콜백함수보다 더 편리한 것을 확인할 수 있습니다. 이전 포스팅에서 작성했던 콜백함수를 이용한 코드를 리팩토링하며 살펴보도록 하겠습니다.
function setTimeoutWithCallback(callbackFunc) {
setTimeout(() => {
console.log('2');
callbackFunc()
},1000);
}
console.log('1');
setTimeoutWithCallback(() => console.log('3'))
const one = Promise.resolve('1');
const two = new Promise((resolve) => setTimeout(() => {
resolve('2')
}, 2000));
const three = Promise.resolve('3');
one.then((oneRes) => {
console.log(oneRes)
return two;
})
.then((twoRes) => {
console.log(twoRes)
return three;
})
.then((threeRes) => {
console.log(threeRes)
})
.finally(() => console.log('END'))
이를 아래와 같이 조금 더 확장해 코드를 작성하면 .then
과 같은 사용 없이 비동기를 조금 더 명시적으로도 작성할 수도 있습니다.
const two = (delay) =>
new Promise((resolve) =>
setTimeout(() => {
resolve('2')
}, delay));
resolve
와 reject
를 모두 사용하는 간단한 예제를 하나 더 작성을 해보겠습니다.
const starbucks = function (coffeeName) {
return new Promise((resolve, reject) => {
if (coffeeName === '아메리카노') {
resolve('아메리카노 한잔입니다.');
} else {
reject('아메리카노는 없습니다.')
}
})
}
starbucks('아메리')
.then((res) => console.log(res))
.catch((rej) => console.log(rej))
.finally(() => console.log('감사합니다'));
//output
아메리카노는 없습니다.
감사합니다
starbucks('아메리카노')
.then((res) => console.log(res))
.catch((rej) => console.log(rej))
.finally(() => console.log('감사합니다'));
//output
아메리카노 한잔입니다.
감사합니다
Promise
를 처음 배우는 경우 새로운 용어들에 의해 아직은 어려울 수 있지만 조금이라도 친숙해진다면 자유롭게 코드를 작성할 수 있을 것입니다