Promise 객체는 비동기 작업이 처리 된 후 미래의 성공, 실패, 그 결과 값을 나타낸다.
Promise는 생성될 때 확실하지 않은 미래의 결과 값을 위한 대리자로,
비동기 연산이 종료된 이후에 결과 값이나, 실패 이유를 처리하기 위한 handler들을 연결 할 수(Chaining) 있도록 한다.
코드로 쉽게 알아보자면,
아래와 같은 .then, .catch, .finally 와 같은 Chaining된 handler들이,
axios와 같은 비동기 연산을 처리할때 자주 사용된다.
axios.get('/gillog', {
params: {
ID: 1
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
이는 다음과 같은 비동기 요청이 실행 된 이후에 axios.get('/gillog', {params: {ID:1}});,
정상적으로 실행이 완료되면 .then을 통해,
비정상적으로 실행이 되어 에러가 발생할 경우 .catch를 통해 처리하는 형태이다
Promise를 사용함으로 써 비동기 메소드를 마치 동기 메소드 처럼 값을 반환하며 사용할 수 있게 해준다.
다만 최종 결과를 반환하지는 않고, Promise를 반환하여 미래 특정 시점(정상, 에러, ..)에 결과를 반환한다.
Promise는 아래 세 가지 중 하나의 상태를 가진다.
대기(Pending) : 이행하거나 거부되지 않은 초기 상태
이행(Fulfilled) : 연산이 성공적으로 완료
거부(Rejected) : 연산이 실패
대기(Pending) 중인 Promise는 값과 함께 이행(Fulfilled) 될 수도,
오류로 인해 거부(Rejected)될 수도 있다.
이행(Fulfilled), 거부(Rejected) 될때 Promise에 연결한 처리기는 .then() method에 의해 대기열에 오른다.
이미 이행(Fulfilled)했거나, 거부(Rejected)된 Promise에 연결한 처리기도 호출하므로,
비동기 연산과 처리기 연결 사이에 경합 조건은 없다.

Promise.prototype.then() 과 Promise.prototype.catch()의 반환 값은 별도의 다른 Promise로
서로 Chaining하여 사용할 수 있다.
iterable 내 모든 Promise가 이행한 뒤 이행하며,
특정 Promise가 거부하는 즉시 해당 Promise를 반환한다.
반환된 Promise가 이행하는 경우, iterable 내 Promise가 결정한 값을 모은 배열이 이행 값이 된다.
반환된 Promise가 거부하는 경우, iterable내 거부한 Promise의 이유를 모은 배열이 이행 값이 된다.
Promise.all은 결국 여러 Promise의 결과를 모을 때 사용한다.
iterable 내의 특정 Promise가 이행, 거부 하는 즉시 스스로 이행 하거나,
거부하는 Promise를 반환한다.
이행 값이나 거부 이유는 반환 Promise의 값이나 이유를 그대로 사용한다.
해당 이유로 거부하는 Promise 객체를 반환한다.
해당 값으로 이행하는 Promise 객체를 반환한다.
값이 .then 가능한(.then method가 있는) 경우,
반환된 Promise는 .then method를 따라가고 마지막 상태를 띈다.
.then이 불가능한 경우, 반환된 Promise는 주어진 값으로 이행한다.
만약 어떤 값이 Promise인지 아닌지 모를 경우에,
Promise.resolve(value) 실행 후 반환 값을 Promise로 처리할 수 있다.
Promise를 사용하는 script를 코드와 함께 살펴보면 아래와 같다.
let firstPromise = new Promise((resolve, reject) => {
setTimeout(function(){
resolve("log!");
}, 250);
});
firstPromise.then((successMessage) => {
console.log("Gil! " + successMessage);
});
// after 2.5초
// Gil! log!
위 firstPromise는 Promise 생성자로 생성된 Promise 객체로,
이행되는 결과는 2.5초 이후에 log! 라는 값을 반환하며 이행한다.
그 후 해당 Promise객체인 firstPromise.then chaining을 통해,
해당 비동기 연산( resolve("log!");)를 이행한 후에 console.log()로 "Gil! " 와 함께,
비동기 연산 결과를 로그 찍는 간단한 Promise 실행 예제이다.
var promiseCount = 0;
function testPromise() {
var thisPromiseCount = ++promiseCount;
// [1]
console.log("동기 연산 실행 시작!");
// 새 프로미스 생성 - 프로미스의 생성 순서를 전달하겠다는 약속을 함 (3초 기다린 후)
var p1 = new Promise(
function(resolve, reject) {
// [2]
console.log("비동기 연산 시작!");
window.setTimeout(
function() {
// [4]
// 프로미스 이행(resolve) !
// 해당 프로미스 카운트 반환
resolve(thisPromiseCount);
}, Math.random() * 2000 + 1000);
}
);
// 프로미스를 이행했을 때 할 일은 then() 호출로 정의하고,
// 거부됐을 때 할 일은 catch() 호출로 정의
p1.then(
function(val) {
// [5]
console.log("비동기 연산 이행 이후 then 실행 ! 결과 = " + val);
})
.catch(
function(reason) {
console.log('거부된 프로미스(' + reason + ')를 처리.');
});
// [3]
console.log("동기 연산 실행 종료!");
}
위 testPromise() method는 Promise 객체를 포함하는 method로
해당 testPromise() 실행 시 Promise 비동기 연산과 동기 연산의 동작 과정을 나타내주는 method 이다.
먼저 전역으로 선언한 promiseCount를 ++promiseCount 하여 thisPromiseCount에 저장하고,
console.log("동기 연산 실행 시작!");를 통해 동기 연산 과정에 실행을 알린다.
그 후 p1이라는 Promise 객체를 생성하는데,
해당 객체는 console.log("비동기 연산 시작!");를 통해 Promise 객체 안에서 비동기 연산이 실행되는 시점을 알려주고,
Math.random() * 2000 + 1000인 랜덤한 시간 이후에 해당 Promise를 resolve()를 통해 이행(resolve) 한다.
이행 결과 값으로 thisPromiseCount 값을 반환하고,
해당 Promise 객체 p1에 .then()(이행 후 실행 될 chaining 연산)으로는,
이행 결과 값과 함께 console.log("비동기 연산 이행 이후 then 실행 ! 결과 = " + val);를 log 찍도록 선언되어 있다.
그리고 console.log("동기 연산 실행 종료!"); 와 함께 testPromise()의 실행은 종료된다.
실제 실행 결과는 아래와 같다.

[1] > [2] > [3] > [4] > [5] 순
이를 통해 Promise를 사용할 때 동기, 비동기 연산의 동작 과정을 알 수 있다.