Ryu.log

[ JavaScript ] Axios와 async/await을 통한 콜백 지옥 탈출 본문

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로 빠지기 때문에
요청에 실패한다면 디버깅이 어렵다는 단점이 있다.

'Prev-content' 카테고리의 다른 글

[ Webpack ] CRA(create-react-app) Webpack sass-loader 기본 루트 설정  (0) 2019.01.24
Array.prototype.splice()  (0) 2018.11.13
Array.prototype.unshift()  (0) 2018.11.13
Array.prototype.shift()  (0) 2018.11.13
Array.prototype.pop()  (0) 2018.11.13
Comments