4주차 강의를 모두 듣고 과제를 진행했는데 Promise 기반으로 구현된 fetch 통신 코드를 async/await 기반으로 리팩토링하는 것이었습니다. async/awit 기반에 try-catch로의 리팩토링은 무난히 끝났지만...
그런데 이게 무슨 일이야,,,?
then-catch러 구현하려고 할 때 예상치 못한 에러가 발생했습니다.
일단 try-catch로 리팩토링한 코드부터 보시죠
1. try-catch
class HttpError extends Error {
constructor(response) {
super(`${response.status} for ${response.url}`);
this.name = 'HttpError';
this.response = response;
}
}
단순히 에러를 던져주는 커스텀 클래스입니다. 이 부분은 고정 변하지 않습니다.
async function loadJson(url) {
let res = await fetch(url);
if (res.status == 200) {
return res.json();
} else {
throw new HttpError(res);
}
}
fetch 요청을 비동기적으로 처리하고, await을 사용하여 응답을 기다립니다.
응답 코드가 200일 경우 응답 데이터를 json 형식으로 변환하여 return 해줍니다.
에러가 발생할 경우 HttpError를 던집니다.
async function koreanMovie() {
try {
let res = await loadJson(`https://klassic-quote-api.mooo.com/v1/random-quot`);
console.log(res);
console.log(`${res.author}: ${res.quote}`);
alert(`${res.author}: ${res.quote}`);
} catch (err) {
if (err instanceof HttpError && err.response.status == 404) {
console.log(err);
alert("무언가 에러가 발생했군요!");
return koreanMovie();
} else {
alert("알 수 없는 에러:", err);
throw err;
}
}
}
loadJson 함수에서 응답을 무사히 받으면 값을 출력해주고
에러가 발생하면 재귀 호출로 koreanMovie를 다시 실행시켜주도록 구현했습니다.
이제 then-catch 형식으로 리팩토링 했을 때 입니다....
2. then-catch
async function loadJson(url) {
await fetch(url).then((res) => {
if (res.status == 200) {
return res.json();
} else {
throw new HttpError(res);
}
});
}
await을 통해 Promise가 반환될 때까지 기다리고 성공적으로 반환되면 json 형식으로 변환하여 반환합니다.
async function koreanMovie() {
await loadJson(`https://klassic-quote-api.mooo.com/v1/random-quote`).then((res) => {
console.log(res);
console.log(`${res.author}: ${res.quote}`);
alert(`${res.author}: ${res.quote}`);
}).catch((err) => {
console.error(err);
alert(err);
}
)
}
여기서 문제가 발생했습니다.

왜 author를 읽지 못해...
혹시 몰라서 console을 추가해봤지만 돌아오는 것은 undefined 뿐...

이제 마지막으로 네트워크 창에 들어가서 데이터 응답이 잘 됐나 확인 해봤는데

넌 또 왜 들어있니....?

그렇다면 문제는
async function loadJson(url) {
await fetch(url).then((res) => {
if (res.status == 200) {
return res.json();
} else {
throw new HttpError(res);
}
});
}
이 쪽에서 반환을 못했기 때문
return res.json() 이 있지 않냐고요?
네, 저도 그럴 줄 알았습니다.
그 return 값은 콜백 함수의 값으로 then 내에서만 영향을 미칠 뿐 외부 스코프까지 영향을 못 미치기 때문입니다... 따라서 await 앞에 return을 작성하여 then 메서드의 결과값이 상위 컨텍스트까지 전달할 수 있도록 만들어야 합니다.
async function loadJson(url) {
return await fetch(url).then((res) => {
if (res.status == 200) {
return res.json();
} else {
throw new HttpError(res);
}
});
}
이렇게 하면 loadJson 함수를 실행시킬 시 res.json()이 반환값이 됩니다.
실행 컨텍스트 공부하러 가야겠습니다.....✨