- Published on
promise.then(f, f) vs promise.then(f).catch(f) 는 무엇이 다를까?
- Author
- Name
- yceffort
자바스크립트에서는, promise의 성공과 실패에 따른 콜백을 두가지 방법으로 처리할 수 있다.
promise.then(oSuccess, onFailure)
promise.then(onSuccess).catch(onFailure)
이 두 가지는 무엇이 다른걸까?
일단, 각각 성공과 실패에 따른 콜백을 아래와 같이 선언한다고 가정해보자.
function onSuccess(value) {
console.log('Promise has been resolved with value:', value)
}
function onFailure(error) {
console.log('Promise has been rejected with error:', error)
}
먼저, resolve
의 경우를 살펴보자.
Promise.resolve('Hi').then(onSuccess, onFailure) // Promise has been resolved with value: Hi
Promise.resolve('Hi').then(onSuccess).catch(onFailure) // Promise has been resolved with value: Hi
특별한 것 없이 둘다 동일한 결과를 보인다.
이번엔 둘다 실패했을 때를 가졍해보자.
Promise.reject('Sorry').then(onSuccess, onFailure) // Promise has been rejected with error: Sorry
Promise.reject('Sorry').then(onSuccess).catch(onFailure) // Promise has been rejected with error: Sorry
이번에도 동일하다.
이 둘의 차이는, 바로 resolve
에서 rejected
가 발생할 때 알 수 있다.
function onSuccessButRejected(value) {
console.log('Promise has been resolved with value:', value)
return Promise.reject('Oops, Sorry')
}
Promise.resolve('Hi').then(onSuccessButRejected, onFailure)
// Promise has been resolved with value: Hi
// Promise {<rejected>:"Oops, Sorry"}
// Uncaught (in promise) Oops, Sorry
Promise.resolve('Hi').then(onSuccessButRejected).catch(onFailure)
// Promise has been resolved with value: Hi
// Promise has been rejected with error: Oops, Sorry
// Promise {<fulfilled>:undefined}
catch
는, then
내부에서도 reject
가 발생했을 때에도 호출된다.
흐음... 🤔 ...
그렇다면 이건 어떨까?
Promise.resolve('Hi').then(onSuccessButRejected).then(null, onFailure)
// Promise has been resolved with value: Hi
// Promise has been rejected with error: Oops, Sorry
Promise.resolve('Hi').then(onSuccessButRejected).catch(onFailure)
와 동일하게 동작하는 것을 알 수 있다. 그렇다면, 둘 중에 무엇을 쓰는게 맞을까?
일반적인, if/else
구문과, try/catch
구문을 상상해보자. if/else
는 내가 예측할 수 있는 경우를 else
로 처리한다. 반면, try/catch
는 내가 예측할 수 있는 경우를 포함하여 모든 경우의 수가 catch
로 처리된다. 따라서, 내가 잠재적으로 처리하고 싶은 명확한 failure가 있다면, promise.then(oSuccess, onFailure)
를 쓰는 것이 부수효과(side effect)를 방지하는데 있어 도움이 된다. 반면 promise.catch(onFailure)
는 내가 예측하지 못한 경우를 포함한 모든 에러 - 지정된 작업이 성공처리가 되지 않거나, 비동기 흐름으로 인해 발생하는 오류 - 를 처리할 때 사용하는 것이 좋을 것 같다.
예를 들어, axios를 사용하는 시나리오를 가정해보자.
axios
.get('/api/user/123')
.then(
(value) => {
// 성공
console.log('user info', JSON.parse(value))
},
(error) => {
// http 에러 (40x, 50x...)
console.log('http error', error.response.status)
},
)
.catch((error) => {
// 예측하지 못한 에러
console.log('Unexpected Error!', error)
})
첫번째 then
문에서 resolve
로 정상적으로 응답이 왔을 때 (2xx, 3xx) 처리를 하고 있고, reject
로 http request에러 (4xx, 5xx)처리를 하고 있다. 그리고 마지막 catch
문에서는 예측하지 못한 에러를 핸들링하고 있는데, 이 경우는 JSON.parse
에 실패하는 경우 등의 시나리오에서 호출 될 것이다.