티스토리 뷰

 

Promise 란

Promise는 javascript안에 내장되어 있는 객체이며 비동기 적인 것을 수행할 때 콜백함수 대신 유용하게 사용할 수 있는 객체이다.

 

Promise의 state

Promise는 다음 중 하나의 상태를 가진다.

  • 대기(pending): 연산을 수행중이거나 거부되지 않은 초기 상태
  • 이행(fulfilled): 연산이 성공적으로 완료됨
  • 거부(rejected): 연산이 실패함

 

 

Producer vs Consumer

Promise는 원하는 기능을 수행해서 해당 데이터를 만들어내는 Producer와 데이터를 소비하는 Consumer로 나뉘어진다.

 

Producer


const promise = new Promise(() => {
	setTimeout(() => {
    	// resolve('user id is ...')
        // reject(new Error('no network'));
    }, 2000);
});

Promise 객체를 생성하여 Promise에서 실행 되어야 하는 코드를 정의한다. 

Promise 객체를 만드는 순간 executor 함수가 바로 실행되는데,

생성과 동시에 Promise 내에 정의한 setTimeout가 실행되고 setTimeout이 정상적으로 작동한다면 resolve함수가 반환되며 에러가 발생할 경우 reject함수가 반환된다.

 

Consumer


promise
	.then(value => {
		console.log(value);
	}).catch(error => {
    		console.log(error);
   	 }).finally(() => {
    		console.log('finally');
    	});

consumer 프로세스는 then, catch, finally로 나누어 설명할 수 있다.

promise 객체가 성공적으로 실행될 경우 then에서 resolve의 return 값을 반환받고

promise 객체가 에러를 발생시킬 경우 catch에서 reject의 return값을 반환받는다.

마지막으로 promise의 resolve와 reject에 관계없이 finally가 실행되면서 promise의 consumer  프로세스가 완료된다.

 

 

 

Promise Chaning

// 3. Promise chaining
const fetchNumber = new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 1000);
});

fetchNumber
// 여기에서 num은 resolve에 파라미터로 전달된 값을 의미
.then(num => num * 2)
.then(num => num * 3)
.then(num => {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(num - 1), 1000);
    });
})
.then(num => console.log(num));

promise는 then에서 resolve를 통해 반환받은 값을 전달받아 계속적으로 처리할 수 있다.

첫번째 then에서 resolve에서 반환한 1을 num으로 전달받고 곱하기 2를 해준다.

두번째 then에서 첫번째 then에서 반환한 결과값 2를 num으로 전달받아 곱하기 3을 해준다.

세번째 then에서 두번째 then에서 반환한 결과값 6을 num으로 전달받아 새로운 Promise 생성자의 resolve에 값을 전달한다.

새로운 Promise 생성자의 resolve에서 num에 1을 빼주고 있으므로 최종적으로 반환되는 값은 5이다.

 

Promise를 사용한 Error Handling

Promise를 한꺼번에 여러개를 사용하다보면 어느 Promise객체에서 Error가 발생했는지 알 수 없는 경우가 있다.

이러한 경우를 대비해 하나의 Promise 객체 then마다 catch 함수를 바로 붙여서 에러가 발생하면 이렇게 처리해줘라는 과정을 덧붙이면 어디에서 에러가 발생했는지 직관적으로 알 수 있다.

 

const getHen = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve('hen'), 1000);
    });
const getEgg = hen => 
    new Promise((resolve, reject) => {
        //setTimeout(() => resolve(`${hen} => egg`), 1000);
        setTimeout(() => reject(new Error(`error! ${hen} => egg`), 1000));
    });
const cook = egg => 
    new Promise((resolve, reject) => {
        setTimeout(() => resolve(`${egg} => fri`), 1000);
    });

getHen()
    .then(getEgg)
    .catch(error => {
        return 'bread';
    })
    .then(cook)
    .then(console.log)
    .catch(console.log)

위 코드는 getHen, getEgg, cook 함수를 통해 각각 hen, egg, fri를 반환받는 Producer과정을 정의한 후

세 개의 함수를 then으로 묶어서 Consumer과정을 거친다. 

만약 Consumer과정에서 적어도 하나의 함수에서 에러가 발생한다면 프로그램이 끝까지 실행되지 않고 에러를 발생시키고 종료될 것이다. 

하지만 각각의 Promise의 then에 catch로 에러가 발생할 경우 이런 것을 실행해줘라는 명령을 덧붙인다면 단순히 에러를 발생시키고 프로그램이 종료되지 않고 에러가 발생된 함수에 대해서만 명령한대로 처리를 할 것이며 프로그램은 끝까지 실행될 것이다.

 

Promise.all

아래 코드에서 a와 b모두 Promise로 정의된 비동기일 때 Promise.all 메소드에 인자로 넣어주면 인자로 넣어준 모든 비동기(promise)가 실행완료된 시점에 callback을 실행하도록 할 수 있다.

let a = Promise.resolve(10);
let b = Promise.resolve(20);
Promise.all([a, b]).then(function([resA, resB]) {
	console.log(resA + resB);	// 30
});

 

 

사용자가 화면에 진입했을 때 여러개의 api를 통해 데이터를 받아와서 모든 api 통신과 처리가 완료된 후 완성된 화면을 사용자에게 노출하여야 하는 상황에서 Promise.all을 사용하였다.

처리중일 경우 로딩바를 화면에 노출시키고 Promise.all이 완료되었을 때 사용자에게 화면을 노출하는 방식으로 구현하였다.

 

Promise.all을 찾다가 Promise를 정확하게 다시 공부해야 겠다는 생각이 들어 포스팅을 작성하게 되었는데 

async와 await의 개념에 대해서도 더 깊게 공부해야겠다는 생각이 들었다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함