본문 바로가기
IT 개발

[드림코딩]자바스크립트 기초 정리 ⑨ 프로미스 Promise 개념 및 활용

by gorokeya 2021. 6. 24.

Promise 프로미스란?

자바스크립트서 제공하는 비동기 간편하게 처리 가능하게 하는 오브젝트이다

정해진 장시간의 기능을 수행하고 정상적으로 수행됐다면 성공의 메시지와 처리된 결괏값 전달해주고

만약 예상치 못한 문제 발생하면 에러를 전달해준다

 

 

드림코딩에서 새로운 강의를 런치할때 미리 수강생을 받기로 했다 (이메일을 통해서 미리 등록받는 시스템)

그래서 한 사람이 등록을 완료하면 몇시간, 며칠 뒤 코스 오픈하면 바로 메일로 공지가 발송된다

이는 준비되기 전 미리 등록해놔서 수업이 완료되자마자 공지를 받은 것이다.

 

이미 오픈 된 뒤에 다른사람이 강의 신청하면 이미 수업이 오픈되어있어서 기다릴 필요 없이 바로 메일 공지를 받고

바로 수업에 참여가 가능하다.

 

콜백을 쓰지않고 프로미스 오브젝트를 통해 비동기 코드를 깔끔하게 처리하는 방법에는

프로미스 사용시에 두 가지 포인트를 생각한다

  1. 프로세스가 무거운 오퍼레이션 수행 중인지, 기능 수행 완료되어 성공했는지 (어떤 상태인지 이해하기)
  2. 프로듀서와 컨슈머 견해의 차이를 이해하기

 

 

프로미스가 만들어져서 우리가 작성한 오퍼레이션이 수행 중 일때는 pending 상태이다

이 오퍼레이션을 성공적으로 끝내면 fullfield 상태, 잘 안되면 rejected 상태가 된다

프로미스에는 우리가 원하는 기능을 수행해서 해당 데이터를 만들어내는 프로듀서와 원하는 데이터를

소비하는 컨슈머로 나눠진다.

 

프로미스는 클래스여서 new 키워드를 통해 오브젝트 생성이 가능하고, 프로미스는 또 다른 두가지의 콜백함수를 받는다

기능을 정상적으로 수행해서 마지막의 최종 데이터를 전달하는 resolve와

기능 수행하다가 중간에 문제가 생기면 호출하는 reject 콜백함수가 있다

 

 

보통 프로미스안에서 헤비한 작업을 한다

네트워크에서 데이터 받아오거나 파일에서 큰 데이터 읽어오는 과정은 시간이 꽤 걸려서

동기적으로 처리하면 이걸 처리하는 동안 다음라인의 코드 실행안됀다

그래서 시간 좀 걸리면 프로미스로 비동기적 처리하는게 좋다

 

사용자가 버튼을 눌렀을때만(요청했을때) 네트워크 요청을 해야하는 경우라면

프로미스 안에서 작성하면 안되는데 이는 불필요한 네트워크 통신이 되어버리기 때문이다

 

새로운 프로미스 만들면 우리가 전달한 executor 함수가 바로 자동적으로 실행된다는 것을

염두에 두고 코드 작성해야함

 

 

이렇게 작업이 정상적으로 작동되면 resolve 콜백함수를 호출한다.

성공적으로 네트워크에서 받아온, 가공된 데이터를 resolve 콜백함수를 통해 전달하면 된다.

이 프로미스는 2초 정도 무언가를 하다가 일을 잘 마무리해서 resolve 콜백함수 호출하면서

'ellie'라는 값을 전달해 주는 프로미스이다

 

 

이제 이것들을 이용하는 컨슈머 만들기(then, catch, finally)

값이 정상적으로 작동된다면 (그러면 then) 값을 받아올거라는 가정하에 원하는 기능을 수행하는 콜백함수를 전달한다

value라는 파라미터는 프로미스가 잘 수행되어서 마지막에 resolve 에서 전달된 'ellie'라는 값이 들어온다

콘솔로 찍어보면, 콘솔창에 엘리라는 값이 잘 출력되었다

 

 

네트워크가 잡히지 않아서 에러가 났다는 가정하에 reject 콜백함수를 반환해보자

옆에 Uncauht는 잡히지 않았다고 얘기하는데 이러한 에러핸들링을 하기 위해선

프로미스에서 then은 성공적인 케이스를 다룬다면 catch 는 에러가 발생할때 어떻게 처리할건지

콜백함수를 등록한다

 

 

이렇게 catch를 이용하여 error 를 보내주면 콘솔창에 Uncaught 대신 우리가 보내준 error 메세지가 출력된다.

여기서 then 을 호출하게 되면 다시 프로미스를 리턴하게 되고 리턴된 프로미스에 캐치를 등록하는 것이다

 

 

finally는 최근에 추가됐고, 성공 실패 상관없이 무조건 호출된다.

어떤 기능을 마지막으로 수행하고 싶을 때 finally 사용

 

 

then 은 값을 바로 전달해도 되고, 비동기인 프로미스를 다시 전달해도 가능하다

여러가지를 동시에 묶어서 처리가 가능!

 

결괏값으로는 5가 출력된다

 

 

여기서 콜백함수 전달할때 받아오는 value를 다른함수로 바로, 하나로 호출하는 경우에는 위와같이 생략이 가능하다

(한가지만 받아서 그대로 전달하는 경우)

하지만 한줄로 넣으면 가독성 좋지않다 (줄이면 자동으로 한 줄로 변함)

 

 

이럴땐 첫 번째 줄 옆에 주석처리해주는 // 을 작성하면 알아서 병렬적으로 정렬이 된다

 

 

만약 달걀을 받아오는 과정에서 reject가 발생하면 옆의 콘솔창과 같이

uncaught가 뜬다 (우리가 에러헨들링을 따로 하지 않았기 때문)

 

getHen() 마지막 줄에 catch(console.log) 를 작성하면

에러가 제일 밑으로 전달되어 콘솔창에 캐치가 잘 잡힌다

 

 

계란을 받아올 때 문제가 생겨도 전체 프로미스 체인에 문제가 생기지 않도록 대체를 만든다 (위에선 빵으로 대체)

계란은 못 받아왔지만 요리는 완성됨

즉, 에러핸들링 하고싶은 then의 바로 밑에 catch로 에러핸들링을 하면 된다.

가장 마지막의 catch는 최종적인 에러를 처리한다 (uncaught 방지)

 

 

콜백에서 프로미스로 변경하기

 

 

우선 onSuccess와 onError 지우고, 프로미스 오브젝트 생성한 뒤 setTimeout 함수 안에 코드를 옮겨준다

그리고 onSuccess, Error의 자리에는 각 resolve, reject 콜백함수로 대체한다

 

 

이 부분은

 

 

이렇게 변경이 가능하다.

유저스토리지에서 로그인을 하고 로그인이 성공하면

유저가 전달되니까 그 유저를 이용해 getRoles를 호출하게 되고

모두 다 성공적으로 된다면 최종적으로 받아오는 유저를 이용해서 alert 창을 나오게 한다

 

 

Ref

https://www.youtube.com/watch?v=JB_yU6Oe2eE&list=PLv2d7VI9OotTVOL4QmPfvJWPJvkmv6h-2&index=12 

반응형