비동기 프로그래밍을 구현하기 위해 가장 먼저 사용된 방법이 callBack이었지만, callBack hell이라는 치명적인 문제점이 발생되었다.
이를 해결하기 위해 나타난 Promise에 대해 살펴보자.
자바스크립트 비동기 처리에 사용되는 객체이다.
비동기 작업에 대한 상태와 결과를 가져와주는 역할을 한다.
간단한 예제를 통해 기존의 콜백방식과 프로미스를 비교해보자.
function getData(callbackFunc){
$.get('주소/users?id=1', function(res){
callbackFunc(res);
});
}
getData(function(userData)){
console.log(userData);
});
콜백함수로 유저의 데이터를 가져와서 출력해주는 함수를 전달하였다.
여기에 프로미스를 적용해보자.
function getData(callbackFunc){
return new Promise(function(resolve, reject){
$.get('주소/users?id=1', function(res){
callbackFunc(res);
});
});
}
getData().then(function(userData)){
console.log(userData);
});
똑같이 유저의 데이터를 가져오는 함수이지만, getData().then()
을 실행하여 프로미스가 resolve
를 호출하면 유저의 데이터를 출력한다.
앞의 예제 코드로 살펴보았듯이 new Promise(executor)
를 사용하여 Promise 객체를 만들 수 있다.
function createPromise(something) {
return new Promise(function(resolve, reject) {
if (비동기 작업 성공) {
resolve(value);
} else { // 비동기 작업 실패
reject(error);
}
});
}
const promiseInstance = createPromise(something);
resolve(value)
value
를 인자로 받는다.reject(error)
error
를 인자로 받는다.Promise 객체를 생성한 직후에는 pending(대기/보류) 상태
를 가지게 된다. 여기서 resolve를 호출하면 fulfilled(이행)
으로 변환되고, reject가 호출되면 rejected(거부/실패)
로 변환된다.
처리 결과에 따라 한 번 지정된 상태는 변경되지 않는다.
비동기 처리가 아직 수행되지 않은 상태
👉 resolve
또는 reject
가 아직 호출되지 않은 상태이다.
new Promise(function(resolve, reject){
//...
});
콜백 함수의 인자로 resolve, reject를 넘겨 pending 이후의 상태에 대한 처리를 수행할 수 있도록 한다.
비동기 처리가 성공한 상태
👉 resolve 함수가 호출된 상태이다.
function getFruit(){
return new Promise(function(resolve, reject){
let fruit = 'orange';
resolve(fruit);
});
}
getFruit().then(function(resolvedData){
console.log(resolvedData);
});
resolvedData로 fruit
이 전달되었고, PromiseState가 fulfilled
임을 알 수 있다.
비동기 처리가 실패한 상태
👉 reject 함수가 호출된 상태이다.
function getFruit(){
return new Promise(function(resolve, reject){
let fruit = 'orange';
reject(new Error('❗️ failed ❗️'));
});
}
getFruit().catch(function(err){
console.log(err);
});
Promise 객체 내부의 프로퍼티 state, result의 직접 접근을 불가능하고, then, catch를 이용하여 접근할 수 있다는 것을 알 수 있게 되었다.
- Promise 생성자 함수
- then
- catch
- finally
Promise 객체의 결과 값을 사용해 추가적인 작업을 할 때, then 메소드를 사용한다.
promise.then(onFulfilled, onRejected?)
onFulfilled
Promise가 성공했을 때, 실행되는 콜백 함수로 결과 값을 인자로 받는다.onRejected
Promise가 실패했을 때, 실행되는 콜백 함수로 에러 객체를 인자로 받는다.return
Promise 객체
promise.then(
function(result){ } // handleSuccess
function(error){ } // handleError
);
만약, 작업이 성공한 경우만 다루려면 then에 하나의 handler만 전달하면 된다.
예외 처리를 위해 사용되는 메소드이다.
promise.catch(onRejected)
onRejected
Promise가 실패했을 때, 실행되는 콜백 함수로 에러 객체를 인자로 받는다.return
Promise 객체
promise.then().catch(function(err) {
console.log(err);
});
아래의 2가지 방법으로 Promise의 reject메서드가 호출되어 실패일때만 실행한다.
function getFruit(){
return new Promise(function(resolve, reject){
reject(new Error('❗️ failed ❗️'));
});
}
getFruit()
.then(function(){},function(err){
console.log(err);
})
getFruit()
.then()
.catch(function(err){
console.log(err);
})
Promise의 이행 및 거부 상태에 관계 없이 처리된 경우 무조건 실행되는 메소드이다.
promise.catch(onFinally)
onFinally
Promise가 처리된 후 실행되는 콜백 함수로 어떤 인자도 받지 않는다.return
Promise 객체
function getFruit(){
return new Promise(function(resolve, reject){
let fruit = 'orange';
resolve(fruit);
});
}
getFruit()
.finally(()=> console.log('👜 과일 가져오기 준비 👜'))
.then(function(resolvedData){
console.log(resolvedData);
})
.finally(()=> console.log('🍊 과일 가져오기 완료 🍊'))
Promise의 성공/실패 여부에 관계없이 실행되는 것을 알 수 있다.
즉, finally는 프라미스 결과를 처리하기 위해 만들어진 메소드가 아니다!
📚 학습할 때, 참고한 자료 📚