Prev-content
[ JavaScript ] Axios와 async/await을 통한 콜백 지옥 탈출
류뚝딱
2019. 7. 25. 15:16
Axios인스턴스와 async/await을 통한 콜백 지옥 탈출
LoL-state 프로젝트를 진행하며 Riot API 서버에 접근하여 데이터를 받아오는 통신부분은
Promise
기반의Axios
로 처리했다.
기존 비동기 코드의 콜백지옥을 훌륭하게 탈피한 Promise이지만 작업을 하다보니 처리가 애매한 부분이 생겼다.
import axios from 'axios';
const ApiDefault = {
url : "https://kr.api.riotgames.com/lol",
key : "XXXXXXXXXXXXXX"
}
getLOLData = () => {
let summonerUrl, matchUrl, leagueUrl;
if(this.state.input.length <= 0) {
alert("ID를 입력해주세요") return;
}
summonerUrl = `${ApiDefault.url}/summoner/v3/summoners/by-name/${this.state.input}?api_key=${ApiDefault.key}`;
axios.get(summonerUrl).then( summonerData => {
matchUrl = `${ApiDefault.url}/match/v3/matchlists/by-account/${summonerData.data.accountId}?api_key=${ApiDefault.key}`;
axios.get(matchUrl).then( matchData => {
leagueUrl = `${ApiDefault.url}/league/v3/positions/by-summoner/${summonerData.data.id}?api_key=${ApiDefault.key}`;
axios.get(leagueUrl).then( leagueData => {
this.setState({
summoner: summonerData.data,
match : matchData.data,
league : leagueData.data[0]
});
}).catch( error => console.log("Data가 없습니다."));
}).catch( error => console.log("Data가 없습니다."));
}).catch( error => console.log("Data가 없습니다."));
}
다른 좋은 코드가 있을 수 있겠지만 위와같이 Axios를 통해 Promise기반의 비동기 통신을 할 경우,
처음 날린 요청(Request)
의 응답값을 이용해서 다음 요청을 보내야할 상황에서어쩔수없이 위 코드와같이 콜백 지옥이 발생된다.
Axios
인스턴스와 async/await
을 사용하여 getLOLData()
함수의 콜백지옥을 벗어나보자
getLOLData = async function() {
if(this.state.input.length <= 0) {
alert("ID를 입력해주세요")
return;
}
//...
}
먼저 함수 내에서 await
을 사용하기 위해 함수앞에 async
를 넣어준다.
import axios from 'axios';
const ApiDefault = {
url : "/lol",
key : "XXXXXXXXXXXXXX"
}
ApiDefault.instance = axios.create({ baseURL : ApiDefault.url }); getLOLData = async function() {
if(this.state.input.length <= 0) {
alert("ID를 입력해주세요") return;
}
//...
}
Http요청이 필요함으로 Axios.create()
를 통해 인스턴스를 생성한다.
import axios from 'axios';
const ApiDefault = {
url : "/lol",
key : "XXXXXXXXXXXXXX"
}
ApiDefault.instance = axios.create({ baseURL : ApiDefault.url });
getLOLData = async function() {
if(this.state.input.length <= 0) {
alert("ID를 입력해주세요")
return;
}
try {
const summoner = await ApiDefault.instance.get(`/summoner/v3/summoners/by-name/${this.state.input}?api_key=${ApiDefault.key}`);
const match = await ApiDefault.instance.get(`/match/v3/matchlists/by-account/${summoner.data.accountId}?api_key=${ApiDefault.key}`);
const league = await ApiDefault.instance.get(`/league/v3/positions/by-summoner/${summoner.data.id}?api_key=${ApiDefault.key}`);
this.setState({
summoner: summoner.data,
match : match.data,
league : league.data[0] })
} catch (error) {
console.error('Data 없음',error);
}
}
위와같이 try/catch
문 안에서 await
을 사용하여 요청을보내면 응답받은 값을 같은 스코프 내에서 처리가 가능해져서
훨씬 보기도 편하고, 코드도 간결해지고 콜백 지옥 현상도 발생하지 않는다.
다만 한가지 문제라면 async/await
에서는 요청을 한번에 모아서 보내는 방식이라 catch
부분의 에러의 구분이 되지않는다.
즉, try
안에서 3개의 요청을 보냈지만 이중 어떤것이라도 실패한다면 catch
로 빠지기 때문에
요청에 실패한다면 디버깅이 어렵다는 단점이 있다.