일반적인 try catch문의 문제는 비동기적 코드에는 대응하지 못한다는 것이다.
그렇기 때문에 Promise에는 비동기만을 위해 지원하는 catch문이 따로 존재한다.
Promise catch문 사용법
Promise.resolve("async fail")
.then((res) => {
throw new Error("#1 fail");
return res;
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
return err;
})
Promise에는 정상동작일 때를 위한 then문과
오류처리를 위한 catch문이 존재한다.
첫 번째 then문에서 의도적으로 #1 fail이라는 에러를 생성했고
따라서 두 번째 then문을 패스하여 마지막의 catch문이 실행되게 된다.
catch문을 최하단에 적어줘야 하는 이유
Promise.resolve("async fail")
.then((res) => {
throw new Error("#1 fail");
return res;
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
return err;
})
.then((res) => {
console.log(res.message);
throw new Error("#2 fail");
})
.catch((err) => {
console.log("final err", err);
});
위 코드에서 then문과 catch문을 하나씩 더 추가해 봤다.
첫 번째 catch문에서 #1 fail에러를 잡아냈고
마지막 catch문은 #2 fail에러를 잡아냈다.
이는 첫 번째 catch문 다음의 then문이 정상 동작하여
에러를 다시 뱉어내줬다는 것을 알 수 있다.
catch문을 제일 하단에 적어주지 않는다면 Promise는 멈추지 않고 계속 다음 동작을 이어할 수 있다는 것이다.
각 Promise 블록에 해당하는 catch문을 작성할 것
Promise.resolve("async fail")
.then((res) => {
Promise.resolve().then(() => {
throw new Error("#3 fail");
}); //this promise block doesn't handling err
return res;
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
return err;
})
.then((res) => {
console.log(res.message);
throw new Error("#2 fail");
})
.catch((err) => {
console.log("final err", err);
});
첫 번째 then절 안에 Promise가 중첩해서 정의되었다.
그리고 해당 Promise에는 catch문이 없다.
#3 fail에러는 이 상황에서 잡아내지 못한다.
실행을 해보면 위 코드는 완전히 엉망진창이 돼버린다.
첫 번째 then절에서 기대했던 #3 에러를 잡아내기는커녕 res를 그대로 리턴해버리고
두 번째 then절은 해당 res를 그대로 콘솔에 찍어낸다 -> async fail
세 번째 catch문은 동작하지 않고
네 번째 then절에서 res.message를 출력하려다 res가 undefined라서 message속성을 찾지 못한다.
당연히 해당 console.log에서 에러가 나면서 #2 에러도 동작하지 않고
마지막 catch문은 비동기 에러를 잡는 것이 아닌 res의 message에 접근하지 못하여서 생긴
type에러를 잡아내게 된다.
그러니 반드시 Promise의 블록에 대응되는 곳에 catch문을 작성해야 한다.
// fix it
Promise.resolve("async fail")
.then((res) => {
Promise.resolve()
.then(() => {
throw new Error("#3 fail");
})
.catch(console.log);
return res;
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log("final err", err);
});
해당하는 블록의 제일 하단에 catch문을 작성하자 원하는 데로 동작하게 된다.
우선 첫 번째 then문에 에러발생은 해당 catch문이 잡게 되고
첫 번째 then문은 종료된다.
다음 두 번째 then문에서는 res값인 async fail을 정상적으로 출력하게 되므로
final catch문은 실행될 일 없이 종료된다.
여기서 확인해야 될 것은 첫 번째 then문의 내부 Promise catch문 보다
두 번째 then문이 먼저 실행되고 에러 catch가 동작했다는 것이다.
'Front-end > JavaScript' 카테고리의 다른 글
JS 에러 핸들링 5편 - 에러 객체 커스텀 (0) | 2023.10.30 |
---|---|
JS 에러 핸들링 4편 - async error handling (0) | 2023.08.09 |
JS 에러 핸들링 2편 - catch (0) | 2023.07.29 |
JS 에러 핸들링 1편 - Error 생성자 (0) | 2023.07.28 |
JS 모듈 4편 - ES6 module (0) | 2023.07.25 |