promise를 실생활에 빗대어 설명하면 어느 한 상점에 손님이 물건을 요구하고 해당 상점은 물건을 제작합니다. 손님은 요구한 물건이 나오기 전까지 10초마다 물건의 완성여부를 묻는 행동을 한다고 가정했을 때, 상점측은 "아니요" , "만들다가 실패했어요" 등의 대답을 해줄 수 있다. 이렇게 10초마다 물어보는 비효율적인 상황에서 효율적인 방법을 찾아보면 ? 손님이 자신의 전화번호를 상점에 남기고 완성되거나 실패하면 결과를 자신의 번호로 알려달라 라고 하는 것이 효율적이겠지요. 이런 행위를
promise
라고 하고 js에서도 해당 기능을 하는 promise 함수가 있습니다.
const pr = new Promise((resolve,reject) => {
// code
}
call back
함수라고 합니다 !다음과 같이 초기 promise 함수는 다음과 같은 값을 갖습니다.
- state : pending (대기 상태)
- result : undefined
이후 resolve(value) 가 실행되면 다음과 같은 값을 갖습니다.
- state : fulfilled (성공)
- result : value(인자로 넘긴 value)
만약 reject(error) 가 실행되면 다음과 같은 값을 갖습니다.
- state : rejected(거부됨)
- result : error
--> 코드는 다음과 같이 이행되었을 때와 ,실패했을 때를 구분하여 작성합니다.
.finally ( function() {} ) 를 추가로 붙여주면 성공 , 실패 여부와 상관없이 실행되는 함수를 만들 수 있다.
const f1 = (callback) => {
setTimeout(function() {
console.log("1번 주문 완료");
callback();
},3000);
};
const f2 = (callback) => {
setTimeout(function() {
console.log("2번 주문 완료");
callback();
},3000);
};
const f3 = (callback) => {
setTimeout(function() {
console.log("3번 주문 완료");
callback();
},3000);
};
console.log("시작");
f1(function(){
f2(function() {
f3(function() {
console.log("끝");
});
});
});
콜백 지옥 (콜백 헬 )
이라고 한다.그렇다면 이 문제를 Promise를 이용하여 해결해보자
const f1 = (message) => {
return new Promise((res,rej)=>{
setTimeout(function() {
res("1번 주문 완료");
},1000);
});
};
const f2 = (message) => {
console.log(message);
return new Promise((res,rej)=>{
setTimeout(function() {
res("2번 주문 완료");
},3000);
});
};
const f3 = (message) => {
console.log(message);
return new Promise((res,rej)=>{
setTimeout(function() {
res("3번 주문 완료");
},2000);
});
};
console.log("시작");
f1
.then(res => f2(res))
.then(res => f3(res))
.then(res => console.log(res));
.catch(console.log)
.finally(()=>{
console.log("끝");
});
Promise chaining
이라고 합니다.그렇다면 위 코드에서 f1,f2,f3의 setTimeout 설정 시간을 보면 1초 ,3초 ,2초로 시간대가 모두 다르다. 따라서 모두 다 실행하려면 총 6초가 걸리는 셈인데, 이를 조금 더 빨리 처리할 순 없을까 ?
--> 해결하려면 세개의 promise를 동시에 처리하면서 가장 오래걸리는 시간을 기준으로 한다면
3초 안에 모두 끝낼 수 있지 않겠는가 ??? 이를 위해서 promise all
을 사용하면 된다
Promise.all([f1(),f2(),f3()])
.then(res => {
console.log(res);
});
이처럼 배열로 promise를 넘겨주면 세 개의 프로미스가 끝나야 then 이 실행되게 된다.
reject를 반환하면 페이지 오류가 발생하기 때문에
해당 코드는 페이지를 보여주거나 에러가 발생했을 때는 아예 보여주지 않는 경우에 사용하는 것이 바람직하다.
promise all 과 사용법은 같지만 다른 부분은 race 란 단어를 통해 유추할 수 있듯이
프로미스들이 경주를 하여 가장 먼저 끝낸 프로미스만 실행되고 코드가 종료된다.
따라서 만약 f2에 reject를 걸어놨을 때 promise race 를 이용하면 f1()이 성공적으로 실행되고 f2()의 reject 가 반환되기 전 이미 끝나버린다.
Promise.race([f1(),f2(),f3()])
.then(res => {
console.log(res);
});