비동기처리 : Promise (promise chaining & error handling)

12512 단어 JavaScriptJavaScript

프로미스란, 자바스크립트에서 비동기처리를 간편하게 처리할 수 있도록 돕는 JS내의 오브젝트이다. 콜백 함수 대신 유용하게 쓸 수 있는 오브젝트.

콜백을 쓰지 않고, 프로미스 오브젝트를 통해 비동기 처리를 깔끔하게 처리해보자.

프로미스는 딱 두가지 포인트가 있다.

    1. State
      상태. 프로세스가 무거운 operation을 수행하고 있는 중인지, 아니면 기능수행이 완료되어서 성공했는지, 실패했는지 같은 상태에 대해 이해하는 것이 중요하다.
    1. producer와 consumer의 차이
      원하는 데이터를 제공하는 사람(producer)과, 제공된 데이터를 소비하는 사람의 두 다른 견해를 이해하는 것이 중요하다.

promise의 상태는 프로미스가 만들어져서 내가 지정한 operation이 수행중일 때는 pending 상태가 된다. 이 operation을 성공적으로 다 끝내게 되면 fulfilled state가 된다.
파일을 찾을 수 없거나, 네트워크에 문제가 있다면 rejected state가 된다.

프로미스 생성하기

내가 원하는 기능을 비동기적으로 실행하는 프로미스를 만들어보자
프로미스는 클래스이기 때문에, new라는 키워드를 이용해 오브젝트를 생성할 수 있다
프로미스의 생성자를 보면, executor라는 콜백함수를 전달해주어야 하는데, 이 콜백함수안에는 또 다른 두 콜백함수를 받는다.

기능을 정상적으로 수행해 마지막에 최종 데이터를 전달하는 resolve콜백함수와, 기능을 수행하다 문제가 생기면 호출하게 될 reject 콜백함수로 이루어져있다.

보통 promise안에서는 네트워크에서 무언가를 받아오거나, 파일에서 큰 데이터를 읽어오는 과정은 시간이 많이 걸리는 작업 등의 헤비한 작업을 한다. 이런 작업들을 동기적으로 한다면 데이터를 받아오는 동안 그 다음 코드를 실행할 수 없게 된다. 즉 마냥 기다리고 있어야 한다.

그래서, 프로미스를 만들어 비동기적으로 처리하면 좋다!

프로미스의 특징

프로미스 오브젝트를 생성한 뒤, 콜백함수에 콘솔로그로 문자열을 출력해보자. 별다른 실행 없이 생성만 하였는데, 콜백함수 안의 콘솔로그가 출력되는 것을 볼 수 있다.

프로미스를 만드는 순간, 전달한 executor라는 콜백함수가 바로 실행이 된다는 뜻이다.

이말인 즉슨, 프로미스 안에 네트워크 통신하는 코드를 작성했다면, 프로미스가 만들어지는 그 순간 바로 네트워크 통신을 수행한다는 것이다.

단점은, 불필요한 네트워크 통신을 할 수 있다는 점이다. 사용자가 버튼을 누를 때만 네트워크 통신을 하게 하고 싶은데, 위의 경우 생성되자마자 통신을 시작하기 때문이다. 코드 작성시 유의하기 바란다.

프로미스 사용하기

  • producer
    서버와의 통신을 성공적으로 마쳤을 때, resolve라는 콜백함수를 통해 값을 전달한다.

  • consumer
    then, catch, finally 를 이용해 값을 받아올 수 있다.
    앞서 만든 promise라는 변수에서 값이 정상적으로 수행이 되었다면(.then) 값을 받아와서 원하는 기능을 수행하는 콜백함수 실행!

promise.then((value => {

}))
value라는 파라미터에는 프로미스가 정상적으로 잘 수행이 되어서 마지막 resolve 콜백 함수로 전달한 hello?라는 값이 value에 담기게 된다.

then 이라는 것은, 프로미스가 정상적으로 수행이 되어 최종적으로 resolve 콜백 함수로 전달한 값이 value의 파라미터로 전달된다.

catch를 통해 에러핸들링을 할 수 있다.

finally는 성공하든 실패하든 상관없이 무조건 호출하는 녀석이다.

Promise chaining

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

fetchNumber
    .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))

Error Handling


// 4. Error Handling
const getHen = ()=>
    new Promise((resolve, reject)=>{
        setTimeout(()=> resolve('🐔'), 1000)
    })
const getEgg = hen =>
    new Promise((resolve, reject)=>{
        setTimeout(() => resolve(`${hen} => 🥚`),1000)
    })
const cook = egg =>
    new Promise((resolve, reject)=>{
        setTimeout(()=> resolve(`${egg} => 🍳`), 1000)
    })
     
getHen()
    .then(hen => getEgg(hen))
    .catch( error =>{ // 계란을 받아오는 것에 문제가 생길 경우, 
  		        //전체적인 프로미스 체인에 문제가 생기지 않도록 닭다리를 리턴
        return '🍗'
    })
    .then(egg => cook(egg))
    .then(meal => console.log(meal))
    .catch(console.log)

좋은 웹페이지 즐겨찾기