본문 바로가기
front-end/Vue.js

axios 비동기처리, Promise, async, await

by 모두의 향연 2022. 7. 20.
728x90
반응형

✔️ajax로 비동기 처리 어떻게 했나?

비동기 처리 1: 아파트 정보를 openAPI로 불러옴 → 비동기 처리 2: 주소를 G.L으로 보냄(위/경도) → 아파트 위치 파악

💡문제점? 데이터를 순서대로 불러오지 않으니 동시에 처리됨

💡해결책! async

 

✔️axios란?

  • Vue에서 권고하는 HTTP 통신 라이브러리는 axios
  • Promise 기반의 HTTP 통신 라이브러리
  • 상대적으로 다른 HTTP 통신 라이브러리들에 비해 문서화가 잘되어 있고 API가 다양하다

https://github.com/axios/axios

 

GitHub - axios/axios: Promise based HTTP client for the browser and node.js

Promise based HTTP client for the browser and node.js - GitHub - axios/axios: Promise based HTTP client for the browser and node.js

github.com

https://axios-http.com/kr/docs/intro

 

시작하기 | Axios Docs

시작하기 브라우저와 node.js에서 사용할 수 있는 Promise 기반 HTTP 클라이언트 라이브러리 Axios란? Axios는 node.js와 브라우저를 위한 Promise 기반 HTTP 클라이언트 입니다. 그것은 동형 입니다(동일한 코

axios-http.com

  • axios.get(URL) << Promise 객체를 return >>
  • 그 객체를 리턴하면 then, catch 사용가능

 

 

✔️axios 어떻게 쓰나?

📒npm 방식 : 내 컴퓨터에 자체적으로 설치함

npm install axios

 

📒CDN 방식:

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

 

📒unpkg CDN: Vue2.x에선 인식 x

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

 

 

✔️axios API

: 모양새를 보니 ajax와 비슷하다! 약간의 문법 차이만 있을 뿐이지 다르진 않다!

문서화를 보고 참고해서 사용하면 됨

 

📒POST request

axios({
  method: 'post',
  url: '/user/12345',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});

 

📒GET request

axios({
  method: 'get',
  url: 'https://bit.ly/2mTM3nY',
  responseType: 'stream'
})
  .then(function (response) {
    response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
  });

 

 

✔️axios의 Promise

Promise란 서버에 데이터를 요청하여 받아오는 동작과 같은 비동기 로직 처리에 유용한 자바스크립트 라이브러리이다. 자바스크립트는 단일 스레드로 코드를 처리하기 때문에 특정 로직의 처리가 끝날 때까지 기다려 주지 않는다. 따라서 데이터를 요청하고 받아올 때까지 기다렸다가 화면에 나타내는 로직을 실행해야 할 때 주로 Promise를 활용한다. 그리고 데이터를 받아왔을 때 Promise로 데이터를 화면에 표시하거나 연산을 수행하는 등 특정 로직을 수행한다.

 

[axios는 라이브러리 → promise는 js라이브러리 →  axios는 자동으로 promise객체 return]

 

📒Promise로 직접 작성하기

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        //promise객체 생성
        const promise = new Promise((resolve, reject) => {
            console.log("promise 객체 생성 완료");
            resolve("성공!");
            reject("실패!");
        })

        promise
            .then((response) => {//응답 받았을 때만
                console.log("then" + response);
            })
            .catch((error) => {//에러 발생했을 경우
                console.log("error" + error);
            })
            .finally(() => {//무조건 실행해야하니까
                console.log("finally");
            });
    </script>
</head>

<body>
</body>

</html>

promise는 js라이브러리이며 비동기 처리하려면 if와 then을 계속 써줘야 하는 비동기 호출 지옥에 빠진다..😭

비동기 호출지옥

그래서 axios가 필요한 것이다!

 

 

✔️axios를 이용해보자

1. script에 CDN추가

2. jsonplaceholder에서 테스트용 API 받아오기 or 랜덤 무료 이미지

https://jsonplaceholder.typicode.com/

 

JSONPlaceholder - Free Fake REST API

{JSON} Placeholder Free fake API for testing and prototyping. Powered by JSON Server + LowDB. Tested with XV. As of Oct 2021, serving ~1.7 billion requests each month.

jsonplaceholder.typicode.com

 

 

3. 순수 ajax로 받아오는 코드

        const URL = 'https://jsonplaceholder.typicode.com/todos/1';

        //1. 이전코드
        const xhr = new XMLHttpRequest();
        xhr.open("GET", URL);
        xhr.send();

        const response = xhr.response;
        console.log("1", response);//기다려주지 않으니 실행x

        xhr.onload = function () {
            if (xhr.status == 200) {
                const response = xhr.response;
                console.log("2", response);//언제 호출될 지 모르지=>그래서 promise쓰는거임
            }
        }

 

 

4. axios로 받아오는 코드

  • 'response'에서 'data'를 받고 'data'에서 'id'를 받음(체이닝)
  • 2번(위 코드)은 언제 호출될지 모름- 그래서 axios를 쓰는 이유
  • GET방식은 default
        const URL = 'https://jsonplaceholder.typicode.com/todos/1';
        
	//2.axios
        const promise = axios.get(URL);
        console.log("3", promise);//3번이 먼저 나오는 이유: 실행도중에 먼저 내려와서: <pending>상태가 됨
        promise
            .then((response) => {
                console.log("4", response);
                return response.data;//response가 갖고있는 데이터를 쓰고 싶을 때
            })
            .then((data) => {//체이닝으로 위에서 받은 data를 사용
                console.log("5", data);
                return data.id;//data중에서 id를 리턴하고 싶을 때
            })
            .then((id) => {//체이닝으로 위에서 받은 id를 사용
                console.log("6", id);
            })
            .catch((error) => {
                console.log(error);
            })
            .finally(() => {
                console.log("finally");
            })

 

 

 

5. axios로 받아오는 코드(promise 변수를 따로 선언 X)

  • URL에서 ID부분을 빼고(/뒷부분) 받아옴(URL = 'https://jsonplaceholder.typicode.com/todos') -> 그럼 data가 200개라고 나옴
  • promise 변수를 따로 받을 필요X, axios.get() 자체가 promise객체 받아옴
  • data는 '배열'형태로 되어있고, 그중에 5번째 배열을 가져오는 방법
   <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script>
        const URL = 'https://jsonplaceholder.typicode.com/todos';

        //2.axios
        axios.get(URL)//promise 변수를 따로 받을필요x axios.get자체가 promise객체 받아옴
            .then((response) => {
                console.log("4", response.data[4]);//[4]니까 5번째 있는 id불러옴
                return response.data[4].id;
            })
            .then((id) => {
                console.log("5", id);
                return axios.get(`${URL}/${id}`);//promise를 리턴해줌
            })
            .then((todo) => {
                console.log("6", todo.data.title);
            })
            .catch((error) => {
                console.log(error);
            })
            .finally(() => {
                console.log("finally");
            })
    </script>

 

 

6. then지옥에서 탈출하는 법

위와 같은 코드인데 간결하다. 하지만, 실행하면 에러남

 

💡왜? 비동기처리 되므로 얻어오지 않았는데 실행됨

    <script>
        const URL = 'https://jsonplaceholder.typicode.com/todos';

        function getTodo(URL) {
            const response = axios.get(URL);
            const id = response.data[4].id;
            const todo = axios.get(`${URL}/${id}`);
            console.log(todo.data.title);
        }
        getTodo(URL);
    </script>

 

💡해결책:

  • async: function 앞에 사용한다. function 앞에 async를 붙이면 해당 함수는 항상 프라미스를 반환한다. 프라미스가 아닌 값을 반환하더라도 이행 상태의 프라미스(resolved promise)로 값을 감싸 이행된 프라미스가 반환되도록 한다.
  • await: 값을 받아올 때까지 기다림, async안에서만 사용가능
    <script>
        const URL = 'https://jsonplaceholder.typicode.com/todos';

        async function getTodo(URL) {
            const response = await axios.get(URL);
            const id = response.data[4].id;
            const todo = await axios.get(`${URL}/${id}`);
            console.log(todo.data.title);
        }
        getTodo(URL);
    </script>

 

✔️정리

:이전에는 js의 라이브러리 ajax 비동기 처리를 했는데, 비동기를 순서대로 처리하기 위해 async를 사용했었다.

이제는 Vue에선 axios라이브러리로 비동기 처리하는데, 이전엔 async를 사용했다면 이제는 axios를 사용하면 promise라는 객체를 자동으로 생성해줘서 순서대로(then/catch/finally) 비동기 처리를 가능하게 한다. 아니면 asyncawait를 사용해 then지옥을 탈출할 수 있다.

 

 

728x90
반응형

'front-end > Vue.js' 카테고리의 다른 글

Vue의 module타입  (0) 2022.09.05
API로 아파트 리스트 가져오기  (0) 2022.07.28
Vue.js 컴포넌트  (0) 2022.07.11
Vue.js 이벤트  (0) 2022.07.08
Vue.js 인스턴스 속성(methods, filter, computed, watch)  (0) 2022.07.07