프론트 단에서 데이터를 랜더링할 때, 데이터를 먼저 패치받아야 한다. 따라서 위의 작업은 비동기 방식으로 진행 되어야 한다. 자바스크립트에서 비동기 작업을 처리하는 방법에는 여러가지가 있다. 그 중 몇 가지 방법에 대해 설명하겠다.
콜백함수
function increase(number, callback) {
setTimeout(()=> {
const result = number +10;
if(callback)
callback(result);
}, 1000);
}
increase(0, result => {
console.log(result);
})
하지만 만약 비동기적으로 처리해야할 작업의 수가 많아진다면 어떻게 될까? 작업의 수만큼 콜백의 깊이가 깊어지고 가독성이 매우 나빠지게 될 것이다. 우리는 이러한 상황을 콜백 지옥이라고 부른다.
Promise
Promise는 콜백 지옥 상황을 해결하기 위해 ES6부터 도입된 기술이다. 아래 예시를 통해 Promise의 사용 법을 알아보자. 코드의 로직은 콜백 함수로 구현 한 것과 같다.
function increase(number) {
const promise = new Promise((resolve, reject)=> {
setTimeout(()=> {
const result = number + 10;
if(result > 50) {
const e = new Error('Too Big Number');
return reject(e); //실패하면서 Error 객체 반환
}
resolve(result); //성공하면서 값 result 반환
}, 1000);
});
return promise;
}
increase(0)
.then(number => { // resolve된 값은 .then을 통해서 받아 올 수 있다.
console.log(number);
return increase(number);
})
.catch(err => { // 비동기 실행 도중 reject된 값은 .catch에서 처리한다.
console.log(err);
});
async/await
aysnc/await는 Promise를 더욱 쉽게 사용할 수 있도록 하는 ES2017(ES8) 문법이다. 이 문법의 사용 방법은 비동기 처리하는 함수의 앞에 async 키워드를 추가하고, 해당 함수 내부에서 Promise앞 부분에 await 키워드를 사용한다. increase 함수는 위와 같게 사용한다.
const runTask = async () => {
try {
let result = await increase(0);
console.log(result);
result = await increase(result);
console.log(result);
} catch(e) {
console.log(e);
}
}
runTask();
React에서 데이터 연동하기
데이터를 API요청으로 불러올 때, useEffect 훅을 사용해서 컴포넌트가 처음 렌더링 된 직후에 API요청을 하면 된다. 주의할 점은 useEffect에 등록하는 함수에 async를 붙이면 안 된다는 것이다. useEffect에서 반환해야 하는 값은 뒷정리 함수이기 때문이다.
따라서 useEffect 내부에서 async/await를 사용하고 싶다면, 함수 내부에 async 키워드가 붙은 또 다른 함수를 만들어서 사용해야 한다.
추가로 loading이라는 상태를 두어 API 요청 전후 여부를 저장해 둘 것이다.
import React, { useState, useEffect } from "react";
import axios from "axios";
const NewsList = () => {
const [isLoading, setIsLoading] = useState(true);
const [news, setNews] = useState();
useEffect(() => { // useEffect를 사용해 첫 번째 렌더링을 한 직후 데이터 로드
const fetchData = async () => { // async/await는 useEffect에 사용하지 말고 안에 따로 지정한 함수 안에서 처리
try { // try catch 문법
const res = await axios.get("https://someURL.com");
setNews(res.data);
} catch (e) {
console.log(e);
}
setIsLoading(false);
};
fetchData();
}, []);
if (isLoading) return <div>Loading...</div>; // 로딩중이면 로딩화면 렌더링
if (!news) return <div>No Data...</div>; // 데이터가 존재하지 않으면 그에 따른 처리
return ( // 정상 데이터 렌더링
<div>
{news.map((newsItem, index) => (
<div key={index}>{newsItem}</div>
))}
</div>
);
};
export default NewsList;
'Frontend > JavaScript' 카테고리의 다른 글
JEST (0) | 2021.08.31 |
---|---|
history, location, match (0) | 2021.07.07 |
2020-05-21 :: Promise (0) | 2021.05.21 |
200824 (0) | 2020.08.24 |
200816 DOM (0) | 2020.08.16 |