뉴스 기사와 날씨 정보를 받아오는 getNewsAndWeather
함수를 작성하고 있었다.
Promise를 공부하고 있었기 때문에 의도적으로async/await
는 활용하지 않았다. 예상과 달리 이 함수가 의도대로 동작하도록 만드는 데에는 오랜 시간이 걸렸다.
아래의 두 코드는 같은 의사 코드로 작업했으나 서로 다른 결과를 낸다.
function getNewsAndWeather() {
return fetch(newsURL)
.then(news => {
return fetch(weatherURL)
.then(weather => {
const newsJSON = news.json();
const weatherJSON = weather.json();
return { news: newsJSON.data, weather: weatherJSON };
})
})
// 실행 결과: { news: undefined, weather: {} }
}
function getNewsAndWeather() {
return fetch(newsURL)
.then(news => news.json())
.then(newsJSON => {
return fetch(weatherURL)
.then(weather => weather.json())
.then(weatherJSON => {
return {
news: newsJSON.data,
weather: weatherJSON
};
});
})
.catch((error) => console.log(error));
}
// 실행 결과: { news: [(뉴스 기사들)], weather: {(날씨 정보)}} }
두 코드 모두 fetch then의 전달 인자인 Response 객체(news data, weather data)에 .json()
메서드를 사용하여 자바스크립트 객체 형태로 바꿔준다. 그런데 왜 1번 코드는 newsJSON
, weatherJSON
에 아무것도 담기지 않을까?
함수는 작성했으나 이 문제의 원인을 규명하지 않으면 밤에 잠이 오지 않을 것 같았다. 눈에 띄는 차이점은 .json()
메서드를 사용하는 방식이 다르다는 점이었으므로 일단 .json()
메서드의 명세를 확인해 보았다.
결론부터 이야기 하자면 .json
메서드는 프로미스를 리턴하기 때문에 아래와 같이 사용하는 것은 잘못되었다.
function getNewsAndWeather() {
return fetch(newsURL)
.then(news => {
return fetch(weatherURL)
.then(weather => {
// 의도와 달리 Promise 객체가 담김
const newsJSON = news.json();
const weatherJSON = weather.json();
return { news: newsJSON.data, weather: weatherJSON };
})
})
// 실행 결과: { news: undefined, weather: {} }
}
MDN Fetch API 안내서에 따르면 json()
은 응답 본문 텍스트를 JSON으로 파싱한 결과로 이행하는, 또 다른 프로미스를 반환한다.
이 사실은 Response.json() 문서에 더 자세하게 소개되어 있다.
직역하면 json()
메서드는 프로미스를 리턴하며 body text를 JSON 형식으로 parsing한 결과값을 resolve한다. 즉, 의도한대로 resolve된 결과값을 활용하려면 const newsJSON = news.json()
과 같이 작성해선 안 된다.