본문 바로가기
IT/자바스크립트

[javascript] promise 객체 소개

by 모찌 2018. 8. 14.

Promise란?


promise는 비동기 동작이 완료된 이후 그 성공, 실패한 결과를 처리하기 위한 handler이다. 


현재는 값이 존재하지 않으니까 가져오게 되면 어떻게 처리를 해준다는 일종의 약속이다.


callback 요청에 callback 함수를 실행하는 대신에 객체로 사용하는 것이다. 


동기 : 순차적으로 일을 스스로 끝내 가는 방식(서버 요청이 끝날때까지 기다려주고 결과물을 가져옴)
비동기 : 해야할 일을 맡기고 다음 코드를 실행하는 방식.(서버 요청이 끝나지 않아도 다음을 실행, 나중에 완료되면 가져옴)


Promise 상태


대기 (pending) : 작업을 요청하였으나 아직 성공, 실패의 결과도 받지 못한 대기 상태


이행 (fulfilled) : 작업 요청 후, 처리에 성공한 상태


거부 (reject) : 작업 요청 후, 처리에 실패한 상태


완료 (settled) : 성공, 실패든 작업이 끝난 상태


Promise 사용법


new Promise(function(resolve, reject) { ... } );

Promise 객체를 생성하면 resolve와 reject의 함수를 전달받는다.


작업이 성공하면 resolve함수를 호출하여 resolve의 인자값을 then으로 받게 되고


작업에 실패하면 reject 함수를 호출하여 reject의 인자값을 catch로 받게 된다.


성공, 실패 어떤일이든 finally로 받아서 처리할 수도 있다.

new Promise(function (resolve, reject) {
}).then(function (resolve) {
//resolve 값 처리
}).catch(function (reject) {
//reject 값 처리
}).finally(function(){
//항상 처리
});


Promise 왜 필요한가?


콜백(callback)은 다른 코드의 인수를 넘겨 받아 실행 가능한 코드다. 


이 콜백 함수를 이용해서 비동기 처리가 가능하다. 다음 예시를 보면서 알아보자.

function addTenValue(x, callBack) {
setTimeout(function () {
return callBack(x + 10);
}, 1000);
}

addTenValue(10, function (x) {
console.log(x);
});


addValue는 1초 뒤에 주어진 값에 10을 더하여 callback함수를 실행해준다. 실행해보면 1초뒤에 20이 찍힐 것이다.


 그럼 위와 같이 비동기 처리를 하면 되는데 Promise객체는 왜 필요한 것인가.


addValue함수를 이용해서 주어진 값에 계속 더해주고자 한다면 어떻게 작업할 것인가. 다음 코드를 보면서 알아보자


function addTenValue(x, callBack) {
setTimeout(function() {
return callBack(x + 10);
}, 1000);
}

addTenValue(10, function (x1) {
addTenValue(x1, function (x2) {
addTenValue(x2, function (x3) {
console.log(x3);
})
})
});


단지 10씩 더하는 값을 받고 싶을 뿐인데 위와 같은 콜백 지옥에 빠질 것이다.


계속해서 더하고자 한다면 depth는 증가 될 수 밖에 없다.


자연스럽게 코드 가독성은 떨어진다.


그렇다면 Promise 객체를 이용해서 어떻게 처리할 것인가.


다음 코드를 보면서 알아보자


function addTenValue(x) {
return (new Promise(function (resolve) {
setTimeout(function () {
resolve(x + 10);
}, 1000)
}));
}

addTenValue(10).then(function (result) {
return addTenValue(result);
}).then(function (result) {
return addTenValue(result);
}).then(function (result) {
console.log(result);
});


Promise 객체를 반환하도록 addValue를 변경하였다. Promise의 내부 함수 resolve를 이용해서 인자에 10씩 더했다.

 

then이라는 promise객체 메소드를 사용해서 결과 값을 받아 처리하자.


처음 주어진 10의 인자에 10을 더하고, 그 결과 값에 10을 더하는 작업이 반복 된다.


callback 함수를 이용했을 때보다 더 간결해지고 명확해졌다.


또한  다음과 같은 오류처리도 가능해진다.


function addTenValue(x) {
return (new Promise(function (resolve, reject) {
setTimeout(function () {
if (typeof x !== 'number') {
reject('유효한 타입이 아닙니다.');
}
resolve(x + 10);
}, 1000)
}));
}

addTenValue('').then(function (result) {
return addTenValue(result);
}).catch(function (message) {
alert(message);
});


Promise.race


Promise 객체를 배열로 받아서 가장 먼저 작업이 완료되는 객체의 값을 반환해 준다.


어떤 객체가 먼저 들어갔는지, 성공인지 실패인지 구분이 없다.


가장 빨리 작업을 끝낸 객체의 결과만을 처리해준다.


다음 코드를 보면서 확인해보자

const promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 200, 'a');
});
const promise2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'b');
});

Promise.race([promise1, promise2]).then(function(value) {
console.log(value); // "b"
});
Promise.race([promise1, promise2]).then(function(value) {
console.log(value);
}).catch(function (value) {
console.log(value); // "b"
});


Promise.all


Promise 객체를 배열로 받아서 모든 작업이 완료되면 결과를 배열로 받아서 처리한다.


const promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 200, 'a');
});
const promise2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'b');
});

Promise.all([promise1, promise2]).then(function(value) {
console.log(value); // ['a','b']
});

단, 작업 중 실패한 작업이 존재한다면 실행을 중단하고 실패한 값을 처리한다.

const promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 200, 'a');
});
const promise2 = new Promise(function(resolve, reject) {
setTimeout(reject, 100, 'b');
});

Promise.all([promise1, promise2]).then(function(value) {
console.log(value);
}).catch(function (value) {
console.log(value); // "b"
});




댓글