프로미스(Promise)란?
JavaScript 에서 코드가 순차적으로 일어나는 처리를 동기 처리라 하며,
특정 코드가 처리될 때 까지 기다리지 않고 다음 코드를 먼저 처리하는 걸 비동기 처리라 한다.
이러한 비동기 처리에서 콜백 지옥(Callback Hell) 등의 문제를 해소하기 위해 사용하는 객체,
즉 비동기 처리에서 순차적 처리를 행하기 위해 사용되는 객체가 프로미스(Promise)이다.
Promise 를 꼭 사용해야 하는가?
꼭 그런 건 아니다. 굳이 따지면 비동기 처리 때 Promise 를 사용하지 않는 사용자가 대부분일 것이다.
하지만 앞서 언급했 듯 비동기 처리는 순차적으로 처리하지 않는다는 특징이 있는데,
경우에 따라 비동기 처리를 사용함에도 이를 순차적으로 처리해주어야 할 때가 있다.
예를 들어 비동기 처리 A 가 성공했을 때 B 를 비동기 처리하고, B 가 성공하면 C 를 처리한다 가정할 때,
이렇게 순차적으로 비동기 함수를 호출해야하는 경우가 있을 때 아래와 같은 형태를 지니게 된다.
function test() {
$.ajax({
url: '...',
data: '...,
type: 'post',
success: function(response) {
$.ajax({
url: '...',
data: '...',
type: 'post',
success: function(response) {
$.ajax({
url: '...',
data: '...',
type: 'post',
success: function(response) {
//...
},
error: function(error) {
}
});
},
error: function(error) {
}
});
},
error: function(error) {
}
});
}
이는 error 를 관리하기 힘들 뿐더러 코드 가독성도 떨어지는 콜백 지옥(Callback Hell)에 빠지기 쉽상이다.
이럴 때 Promise 를 사용하면 보다 코드를 간결하게 만들어 주고 처리의 성공과 실패를 쉽게 관리할 수 있게 해준다.
이것이 Promise 를 비동기 처리에서 사용하는 이유인 것이다.
Promise 의 처리 상태 3 가지
지금 껏 말한 Promise 를 사용하기 위해선 3 가지 처리 상태를 숙지해야 한다.
Promise 는 Pending(대기), Fulfilled(이행), Rejected(실패) 처리 상태를 가지며 각 상태의 설명은 다음과 같다.
⊙ Pending(대기) : Promise 객체를 생성하고, 처리 성공 또는 처리 실패 이전까지의 미완료 상태
⊙ Fulfilled(이행) : 처리가 성공적으로 이루어져 Promise 결과 값을 return 해준 상태
⊙ Rejected(실패) : 처리가 실패해 오류가 발생한 상태
각 처리 상태에 대해 순서대로 살펴보자.
Pending(대기)
Promise 객체를 생성했고, 아직 성공이나 실패와 같은 처리 결과가 이루어지지 않은 진행 전 상태를 말한다.
new Promise( ) 로 Promise 객체를 생성하며 인자 값으로 콜백 함수를 넣는다.
이 때 콜백 함수는 처리 성공 때 쓰이는 resolve 와 처리 실패 때 쓰이는 reject 를 인자로 받는다.
//Promise 를 new 로 생성하면 Pending(대기) 상태가 된다
new Promise(function(resolve, reject) {
//...
});
Fulfilled(이행)
방금 말한 콜백 함수에서 어떠한 처리를 수행할테고, 이 처리가 성공하면 인자 값인 resolve 를 수행한다.
new Promise(function(resolve, reject) {
//... 처리 로직 A
//처리 로직 A 가 성공하면 resolve 를 실행
resolve();
});
이렇게 resolve( ) 를 수행하게 되면 Promise 객체는 Fulfilled(이행) 상태가 되는데,
Fulfilled(이행) 상태가 되면 아래와 같이 then( ) 을 이용해 처리 결과를 받아올 수 있다.
function getText() {
return new Promise(function(resolve, reject) {
var text1 = "Hello";
var text2 = "World";
var returnText = text1 + text2 ;
//Fulfilled(이행) 상태가 된다
resolve(returnText);
});
}
//then() 으로 값을 받아온다
getText().then(function(returnText) {
console.log(returnText); //"HelloWorld"
});
Rejected(실패)
Fulfilled(이행) 상태와는 반대로 콜백 함수에서 어떠한 처리를 수행할 때
처리가 실패되면 reject ( ) 를 수행하여 Rejected(실패) 상태로 들어가게 된다.
Fulfilled(이행) 상태는 then( ) 로 받았다면 Rejected(실패) 상태는 catch( ) 로 결과 값을 받아올 수 있다.
function getText() {
return new Promise(function(resolve, reject) {
//... 처리로직
//Rejected(실패) 상태가 된다
reject(new Error("처리 실패"));
});
}
//catch() 로 값을 받아온다
getText().then().catch(function(returnError) {
console.log(returnError); //"처리 실패"
});
그럼 이러한 Promise 의 예제들을 살펴보도록 하자.
Promise 예제 ( 1 )
ajax 통신 사용 예제
서론에서 언급한 ajax 통신의 콜백 지옥을 아래와 같이 탈출할 수 있다.
function test1() {
return new Promise(function(resolve, reject) {
$.ajax({
url: '...',
data: '...',
type: 'post',
success : function(response) {
resolve(); //통신 성공하면 resolve()
},
error: function(error) {
reject(); //통신 실패하면 reject()
}
});
});
}
function test2() {
return new Promise(function(resolve, reject) {
$.ajax({
url: '...',
data: '...',
type: 'post',
success : function(response) {
resolve(); //통신 성공하면 resolve()
},
error: function(error) {
reject(); //통신 실패하면 reject()
}
});
});
}
function test3() {
return new Promise(function(resolve, reject) {
$.ajax({
url: '...',
data: '...',
type: 'post',
success : function(response) {
resolve(); //통신 성공하면 resolve()
},
error: function(error) {
reject(); //통신 실패하면 reject()
}
});
});
}
//처리 성공 함수
function testSuccess() {
console.log("성공");
return false;
}
//처리 실패 함수
function testError() {
console.log("실패");
return false;
}
test1() //test1 실행
.then(test2) //test1 성공하면 test2 실행
.then(test3) //test2 성공하면 test3 실행
.then(testSuccess) //test3 성공하면 처리성공함수 실행
.catch(testError); //test1, test2, test3 에서 각각 처리 실패할 때마다 처리실패함수 실행
이 예제 코드의 전체 흐름은 다음과 같다.
- test1( ) 을 실행하고 처리 로직을 성공하면 test2( ) 를 수행한다.
- test2( ) 을 실행하고 처리 로직을 성공하면 test3( ) 를 수행한다.
- test3( ) 을 실행하고 처리 로직을 성공하면 testSuccess( ) 를 수행한다.
- 이 과정 중 처리 실패가 발생하면 testError( ) 를 수행한다.
Promise 예제 ( 2 )
setTimeout( ) API 사용 예제
new Promise(function(resolve, reject){
setTimeout(function() {
resolve(1);
}, 3000);
})
.then(function(num) {
if(num % 2 == 0) {
console.log("넘어온 num 은 짝수이다");
}
console.log(num); // 1
return result + 1;
})
.then(function(num) {
if(num % 2 == 0) {
console.log("넘어온 num 은 짝수이다");
}
console.log(num); // 2
return result + 1;
})
.then(function(num) {
if(num % 2 == 0) {
console.log("넘어온 num 은 짝수이다");
}
console.log(num); // 3
return result + 1;
});
//실행결과
//1
//"넘어온 num 은 짝수이다"
//2
//3
짝수인 num 을 받아올 때 "넘어온 num은 ..." 로그를 찍는 코드인데
첫 번째 then( ) 에서 받아온 num 은 1 이기에 "넘어온 num은 ..." 로그가 안찍히고,
두 번째 then( ) 에서 받아온 num 은 2 이기에 "넘어온 num은 ..." 로그가 찍힐 것이다.
지금까지 Promise 객체에 대해 알아보았다.
요악하자면 Promise 객체는 비동기 처리때 사용되고 대기, 이행, 실패 처리 상태를 가지고 있다.
처리 성공시 resolve 를 수행해 이행 상태로 바꾸고 이러한 이행 상태의 처리 결과는 then( ) 으로 받는다.
반대로 처리 실패시 reject 를 수행해 실패 상태로 바꾸고 이 처리 결과는 catch( ) 로 받는다.
이 부분만 숙지하면 Promise 를 사용하는 데에 큰 문제 없다고 생각되어진다.
'Coding Story > JAVASCRIPT' 카테고리의 다른 글
[ JavaScript ] 자바스크립트 비구조화 할당 (2) | 2020.11.25 |
---|---|
[ JavaScript ] 자바스크립트 indexOf( ) 함수 (4) | 2020.11.20 |
[ JavaScript ] 자바스크립트 filter( ) 함수와 find( ) 함수 (0) | 2020.11.20 |
[ JavaScript ] 자바스크립트 map( ) 함수 (2) | 2020.11.20 |
[ JavaScript ] 자바스크립트 배열 concat (0) | 2020.11.20 |