#비동기 처리

비동기 상태를 처리하는 방법이 여러 가지가 있고, 콜백 지옥에서 부터 Promise 를 이용한 비동기 처리, axios API 와 async / await 를 이용한 방법까지 진화해보도록 하겠습니다.

#Promise

비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과값을 나타냅니다.

수행시간이 걸리는 작업과 그에 대한 콜백함수를 전달해 줌으로써 작업이 완료( resolve ) 되는 상황에서 callback 이 동작하게 됩니다.

Promise는 다음 중 하나의 상태를 가집니다.

  • 대기(pending): 이행하거나 거부되지 않은 초기 상태.
  • 이행(fulfilled): 연산이 성공적으로 완료됨.
  • 거부(rejected): 연산이 실패함.

#Promise 기본형

function getDataPromise() {
    return new Promise(resolve => {
        setTimeout(function() {
            console.log('요청을 보냈습니다')
            const data = {'data':'some data'} // 데이터 도착
            resolve(data) // 내가 원하는 작업 시작
        },1000)
    })
}
let response = getDataPromise()
console.log(response) // Promise {<pending>} 상태가 출력됩니다.

getDataPromise()
    .then(response => console.log(response)) // 원하는 값인 data를 출력할 수 있습니다

#resolve, reject

function myPromise (url) {
    return new Promise( (resolve, reject) => {
        if (url === 'http') {
            resolve('HTTP 200 OK')
        } else {
            reject('wrong URL')
        }
    })
}
const promise1 = myPromise('http')
console.log(promise1) // fulfilled 상태로 'HTTP 200 OK' 의 값이 담겨 있습니다
				// Promise {<fulfilled>: "HTTP 200 OK"}

const promise2 = myPromise('www') // reject가 되면서 Uncaught 에러가 발생하게 됩니다.
console.log(promise2) // rejected 상태로 완료되었고 'wrong URL' 이 담겨있게됩니다.
				// Promise {<rejected>: "wrong URL"}

promise1
	.then(response => {
    	console.log('성공')
    	console.log(response)
	})
	.catch(error => {
    	console.log('error')
        console.log(error)
	})
// promise1에 then, catch 를 하게 된다면 then() 의 콜백함수가 작동하게 되고
// promise2에 then, catch 를 하게 되면 reject이기 때문에 catch() 의 콜백함수가 작동하게 됩니다.

#fetch & axios

  • AJAX ( Asynchronous Javascript And XML )

    비동기 방식으로 Promise API 를 활용하여 HTTP 통신을 하는 기술이다

  • fetch 는 내장 API 로 비동기 네트워크를 보다 편하게 할 수 있다.

  • axios 는 라이브러리로 사용이 되고 cdn 이나 npm 등을 통하여 설치 후에 사용하게 됩니다.

  • 여러 가지 예외 처리나 기술이 적용되어있고 fetch와의 다른점들이 있습니다.

    • 구형 브라우저를 지원한다
    • 응답 시간 초과를 설정할 수 있다
    • CSRF 보호 기능이 내장되어 있다.
    • JSON 데이터를 자동으로 변환시켜 준다
    • Node.js 환경에서 사용할 수 있다.

#fetch

fetch('https://jsonplaceholder.typicode.com/posts/1/')
    .then(function(response) {
        return response.json();
    })
    .then(data => {
        console.log(data)
    })

첫번째 then 에서 response는 HTTP Response이고 실제 JSON 이 아니게 됩니다.

Response 객체에서 원하는 데이터를 가져오기 위해 .json() 메서드를 사용해 주게 됩니다.

#axios & chaining

const BASE = `http://jsonplaceholder.typicode.com`

axios.get(`${BASE}/posts/1/`)
    .then(response => {
        console.log(response.data.userId) // 1
        return response.data.userId
    })
    .then(userId => {
        return axios.get(`${BASE}/users/${userId}/`)
    })
    .then(response => {
        console.log(response)
        console.log(response.data.name)
    })
  • 처음에 1번 posts 의 정보를 가져오는 요청으로 시작하여 then 요청을 따라가 봅시다
  1. 첫 then 에서는 response의 결과를 받아 해당 data의 userId 를 반환하게됩니다.

  2. 두번째 then 함수에서 userId 를 받아 또다른 axios 요청(유저 정보)을 보내는 데 활용할 수 있습니다

  3. axios 요청을 받은 후의 결과를 response 로 받게 되고 결과적으로 1번 글을 작성한 유저의 이름을 알게됩니다

#async / await

async await 를 사용하여 동기적으로 작동하는 것 처럼 보일 수 있습니다.

async 는 비동기로 작동하는 함수의 앞에 붙여지게 되고,

await 는 Promise객체 앞에 놓아 pending 상태에서 fulfilled상태로 완료될때까지 대기하게 됩니다.

async function getUserName(postId) {
    const posts = await axios.get(`${BASE}/posts/${postId}/`)
    const userId = posts.data.userId
    const users = await axios.get(`${BASE}/users/${userId}`)
    console.log(users.data.name)
}

fetchPost(1)
// postId 를 이용하여 요청을 보내 posts를 알아오게 되고
// 해당 post 의 userId 를 통하여 두번째 요청을 보내서 user 정보를 알아오게 됩니다.

#try catch

Promise 에서 에러처리를 위해 .catch() 를 사용한 것 처럼

async await 에서도 에러처리를 하기 위한 방법으로 try ~ catch 를 사용하게 됩니다.

async function fetchPost(postId) {
    try {
      const posts = await axios.get(`${BASE}/posts/${postId}/`)
      console.log(posts.data)
    } catch (error) {
      console.log(error);
    }
}
fetchPost(1)
  • 기본적으로 postId 를 이용하여 post를 가져오는 형태를 유지하고 있습니다.

  • 하지만 동작하는 과정을 try 로 묶어 주게 되고 아래 catch 처리를 해주게 되면 요청을 보내면서 생기는 에러를 catch() 에서 잡아서 아래의 동작을 수행하게 됩니다.