Promise 체인은 catch()에서 멈추지 않습니다.
그러니까 promise.then().catch().then().catch()가 안 되는건 아닌데..
안 되는건 아닌데, 작성 의도와 다르게 동작합니다. Promise 체인이 멈추지 않습니다.
그래서 엄청 고생했었어요! T_T
하여 Promise 체인의 실행 흐름과 접근 방법을 같이 알아보고,
끝으로 이 글의 숨겨진 주제를(???) 같이 읽어보겠습니다!
편리한 Promise 체인 최고
너무 편합니다.
const promise = getResult();
promise
.then(response => response.json())
.then(data => makeAsyncList(data))
.then(list => console.log({ list }));
여기에 하나씩 catch()를 넣어봅시다
이런 느낌이겠죠?
const promise = getResult();
promise
.then(response => response.json())
.catch(error1 => console.log({ error1 }))
.then(data => makeAsyncList(data))
.catch(error2 => console.log({ error2 }))
.then(list => console.log({ list }))
.catch(error3 => console.log({ error3 }));
문법 에러 없이 잘 동작합니다. 하지만 작성 의도
와는 다르게 동작합니다.
error1이, 혹은 error2가 발생한다면 이 Promise 체인이 멈추길 기대합니다.
하지만 멈추지 않고
, 맨 마지막의 list가 출력됩니다. 정상적이지 않은 데이터로요.
이해를 위해 Promise 체인을 뜯어봅시다
이런 느낌이 될 것 같습니다.
const promise = getResult();
const promise2 = promise
.then(response => response.json())
.catch(error1 => console.log({ error1 }));
const promise3 = promise2
.then(data => makeAsyncList(data))
.catch(error2 => console.log({ error2 }));
const promise4 = promise3
.then(list => console.log({ list }))
.catch(error3 => console.log({ error3 }));
위를 이해하기 위해 우선 알아야 하는 것이 있습니다.Promise.then()
과 Promise.catch()
는 Promise
를 리턴합니다. (참고)
따라서 Promise 체인이 가능한 것이고,
따라서 위처럼 Promise 체인을 한 조각씩 뜯어볼 수 있습니다.
하여 이제는 명확합니다. 실행흐름에 있어 catch()
는 실행 흐름을 멈추지 않습니다.
그래서.. 그러면..?
Promise 체인은 catch()를 하나만 쓸 것을 권장합니다
이런 식으로요! (참고)
const promise = getResult();
promise
.then(response => response.json())
.then(data => makeAsyncList(data))
.then(list => console.log({ list }))
.catch(error => console.log({ error }));
Promise 체인 맨 아래에 catch()
단 하나를 둬서 체인 속 모든 reject
를 여기서 처리하게 합니다.
이 실행흐름은 try-catch
와 닮았습니다. (참고)
async function foo() {
try {
const response = await getResult();
const data = await response.json();
const list = await makeAsyncList(data)
console.log({ list });
} catch(error) {
console.log({ error });
}
}
이제 reject
가 발생하면 남은 Promise 체인을 건너 뛰고, 맨 아래의 catch()
가 실행됩니다.
Promise 체인을 멈추는 데에 성공했습니다! (예이~! ^^)
숨겨진 주제: 서로 다른 곳에서 발생한 에러 다루기
그럼 이제 새로운 고민이 생깁니다.
서로 다른 곳에서 발생한 서로 다른 에러를 한 곳에서 솜씨좋게 다뤄야 합니다. scope가 너무 넓은거죠.
아.. if문이 많이 필요할 것 같아요! (T_T)
하여 선배님들은? 여기서 instanceof
를 쓰기로 하였어요! (참고1, 참고2)
const promise = getResult();
promise
.then(response => response.json())
.then(data => makeAsyncList(data))
.then(list => console.log({ list }))
.catch(error => {
console.log({ error });
if (error instanceof ReferenceError) {
console.log('ReferenceError!');
} else if (error instanceof TypeError) {
console.log('TypeError!');
} else if (error instanceof MyError) {
console.log('MyError!'); // Custom Error Types
}
});
자바스크립트가 함수형 언어이면서도 동시에 객체지향 프로그래밍인 덕분이네요!
그런데 이 부분이 그래서 우리가 아는 if
, switch-case
와 뭐가 다른걸까요?
…를! 알아가는 과정이 아마 객체지향 프로그래밍을 알아가는 과정일 것 같습니다.
하여, 이 글은 여기에서 끝입니다! (잉?ㅎㅎㅎㅎㅎㅎㅎ)