[JavaScript] Promise Chaining 프로미스 체인 쓰는 이유

이은진·2020년 11월 4일
0

JavaScript Study

목록 보기
3/24

목차
1. 콜백함수 및 콜백지옥 알아보기
2. 프로미스로 단순한 방식으로 해결하는 법
3. 프로미스 체인 쓰는 이유, 프로미스 체인으로 더 깔끔하게 해결하는 법

이번 글에서도 콜백함수와 프로미스 코드를 비교하며 프로미스 체인을 쓰는 이유를 간단히 알아본다.

1. 콜백함수 예시

입력한 값이 숫자면 2초 후 2를 곱한 값을 출력하는 간단한 콜백함수다.

const getDataCallback = (num, callback) => { 
  setTimeout(() => { 
    if (typeof num === 'number') {
      callback(undefined, num*2) //error, result
    } else {
      callback('Number must be provided')
    }
  }, 2000)
}

1-1 콜백지옥 예시

2를 곱하는 콜백함수를 두 번 호출해서 8로 만들고 싶어서 다음과 같은 코드를 작성했다.

getDataCallback(2, (err, data) => {
  if (err) {
    console.log(err)
  } else {
    getDataCallback(data, (err, data) => { //두 번 2를 곱하고 싶어서 콜백함수 다시 호출함
      if (err) {
        console.log(err)
      } else {
        console.log(data) //8, 두번째로 2를 곱했으므로 8
      }
    }
    // console.log(data)
    )}
})
//8
  1. This callback hell works anyway despite not the best looking code
    콜백함수를 두 번 호출하는 위 코드에서는 2회 2를 곱한 값을 출력한다는 목적도 달성했고 코드도 문제없이 잘 돌아간다.
  2. To multiply twice, took time twice as long since we do the same thing twice, hard to maintain, challenging to expand, spaghetti code, ... deeply nested
    그런데 두 번 이상 같은 함수를 연결하려다 보니 시간이 두 배나 걸린다. 두 번이 아니라 천 번이라면 유지보수도, 확장도 힘들 것이고 한눈에 알아보기도 힘들 것이다. 이를 콜백지옥이라고 부른다.

2. 프로미스로 단순하게 해결하는 법

const getDataPromise = (num) => new Promise((resolve, reject) => { 
  setTimeout(() => {
    typeof num === 'number' ? resolve(num*2) : reject(console.log('Number must be provided'))
  }, 2000) 
})

instead of using if-else statements, we use separate functions resolve() and reject() preventing us from needing to get nested
앞서 만들었던 콜백함수처럼 if-else문 사용하는 대신 resolve(), reject() 메서드를 각각 사용해서 nesting을 최대한 피한다.

getDataPromise(2).then((data) => {
  getDataPromise(data).then((data) => { //put the data into the getDataPromise() again to multiply twice
    console.log(`Promise data: ${data}`)
  }, (err) => {
    console.log(err)
  })
}, (err) => {
  console.log(err)
})

still need improvement: nesting, duplicate codes
위에서 본 콜백함수 호출 방식보다 훨씬 깔끔하지만 여전히 nesting이 되어 있고, 중복되는 코드가 있다. 이는 프로미스 체인으로 해결할 수 있다.

3. 프로미스 체인

getDataPromise('10').then((data) => {
  return getDataPromise(data)
}).then((data) => {
  return getDataPromise(data)
}).then((data) => {
  console.log(data)
}).catch((err) => { //catch: an error handler for all of our promises in the promise chaining
  console.log(err)
})
  1. Promise chaining is used to better structure things
    프로미스 체인은 코드를 더 효율적으로 짜기 위해서 사용된다.
  2. We dont put then() at the end of getDataPromise(data), return the promise and then chaining. when a promise resolves, the next then() access to the promise before, and chaining starts.
    대제목 2번에서처럼 두 번 함수를 호출하고 싶을 떄 getDataPromise(data)에 then을 붙이는 게 아니라, 일단 getDataPromise(data) 값을 리턴한 후, 마지막에 줄줄이 .then() 메서드를 붙여나간다. 이전 프로미스가 resolve되면 그 다음 프로미스가 실행된다.
  3. Can keep our complex asynchronous code super simple... avoided nesting
    비동기 코드를 아주 간단하게 정리할 수 있다.
  4. Catch(): if either of the promises is rejected, immediately jump down to the error handler function
    여러개의 프로미스 체인 중 하나라도 reject되면 바로 마지막에 달린 catch()로 내려가서 에러를 처리한다. 불필요하게 나머지 프로미스까지 차례차례 확인하지 않음.
profile
빵굽는 프론트엔드 개발자

0개의 댓글