#비동기 처리
비동기 상태를 처리하는 방법이 여러 가지가 있고, 콜백 지옥에서 부터 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 요청을 따라가 봅시다
-
첫 then 에서는 response의 결과를 받아 해당 data의 userId 를 반환하게됩니다.
-
두번째 then 함수에서 userId 를 받아 또다른 axios 요청(유저 정보)을 보내는 데 활용할 수 있습니다
-
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() 에서 잡아서 아래의 동작을 수행하게 됩니다.