상황: TMDB 에서 API 를 통해 영화 데이터를 가져오면서 (TMDB측 에서 받은 fetch코드
fetch('https://api.themoviedb.org/3/tv/top_rated?language=en-US&page=1', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
이 코드를 이해하기 전 알아야 할 점을 정리해본다.
1. fetch ()
- 배경
브라우저에서 fetch() 함수를 지원하기 이전에는, 원격 API호출을 위해 request나 axios, jQuery와 같은 라이브러리를 많이 썼었다. 라이브러리를 썼던 이유로는, 클라이언트 단에서 직접 HTTP 요청하고 응답을 받는 게 상당히 복잡했기 때문이다.
하지만 요즘에는 브라우저에 fetch() 함수가 내장되어 있기때문에, 굳이 이러한 라이브러리의 도움없이 fetch() 함수를 이용해도 충분하다. 오히려 이러한 현재 라이브러리를 사용하는 것이 자바스크립트 번들(bundle) 파일의 크기만 늘려서 낭비가 될 수 있다.
- 쓰는방법
fetch() 함수는 첫번째 인자로 URL, 두번째 인자로 옵션 객체를 받고, Promise 타입의 객체를 반환(=return)한다.
// 기본 골격
fetch(url, options)
.
.
.
fetch(); // Promise();
Promise(); 란?
자바스크립트 비동기 처리에 사용되는 객체다. 여기서 자바스크립트의 비동기 처리란 ‘특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성’을 의미한다.
Promise의 상태(states)에는 3가지가 있는데,
(1) Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
(2) Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
(3) Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태
반환된 Promise 객체는, API 호출이 성공했을 경우에는 응답(response) 객체를 resolve하고, 실패했을 경우에는 예외(error) 객체를 reject합니다.
// 기본 골격
fetch(url, options)
.
.
.
fetch(); // Promise();
Promise(function(resolve, reject) {
resolve(); // respond = { key : value, key1 : value1 ... }
reject(); // error = { key : value, key1 : value1 ... }
};
이러한 과정을 아래와 같은 코드로 표현할 수 있다.
fetch(url, options)
.then((response) => console.("response:", response))
.catch((error) => console.("error:", error))
// API 호출이 성공했을 경우에는 응답 response 객체(= response:)를 resolve하고,
// 실패했을 경우에는 예외error 객체를 reject(= error:)합니다.
.then() / .catch 란 ?
Promise(); 내부에 resolve함수, 또는 reject함수 호출하는 구문이 있을 경우, 둘 중 하나가 실행되면고나면 then(다음), catch(오류)으로 넘어간다. 결국 비동기작업이 완료될때, resolve, reject를 호출한다.
vscode 에서 자주 연습해야하는 사항 : mouseover
vscode에서 코드 단어 위에 마우스를 올려놓으면(클릭x), 아래와 같이 그 단어 또는 함수명에 대한 정보가 뜬다.
위를 해석해보자.
function fetch // fetch 라는 이름을 가진 함수다.
function fetch ( input ) : output // 항상 함수명 소괄호 안에 있는 인자는 input 이다. 또한 소괄호와 콜론 다음에 있는 아이들은 output 이다. 즉, 반환 값이다.
이를 적용해보면, 해석은 이러하다.
fetch 라는 이름의 함수는 input 인자로 총 2개를 받는데
(1) 첫번째로는 input 을 받고
(2) 두번째는 init을 받는다. ? 의 뜻은 들어올수도 있고 안들어올수도 있다는 뜻이다.
그리고 반환값으로는 Promise함수를 반환한다.
아하, fetch() 함수는 항상 Promise() 함수를 반환하는구나!
.then 의 정보도 확인해보자
.then은 promise()함수의 반환값을 받고 가는 함수이기 때문에
Promise<Response>.then의 형태로 간다고 적혀있다.
input인자로 총 두개를 받는데 (1) onfulfilled (2) onrejected 이다. 근데 둘다 ?가 붙어 있는 것을 보니 받을 수도 안받을 수도 있다는 뜻으로 해석된다. 결국 반환값은 또 Promise함수이다.
에러를 처리하는 .catch() 도 동일하게 Promise를 반환한다. 대신 인자는 onrejected 하나를 받는다.
이렇듯,
then 메소드는 계속 Promise()를 반환하기때문에 콜백지옥에 빠질 수 있는 위험이 있다.
그렇기에 이를 대신할 수 있는 함수 async, await 을 쓰는 것이 더 좋을 수 있다.
이러한 Promise ~ then 보다 좀 더 간편하고, 안전하게 쓸 수 있는 문법은
async() 와 await() 이다.
2. async() 와 await()
async
먼저 async 는 함수 앞에 위치한다.
async function f() {
return 1;
}
function 앞에 async를 붙이면 해당 함수는 항상 프라미스를 반환한다. 프라미스가 아닌 값을 반환하더라도 이행 상태의 프라미스(resolved promise)로 값을 감싸 이행된 프라미스가 반환되도록 한다.
async 는 promise를 반환한다
await
자바스크립트는 await 키워드를 만나면 promise가 처리될 때까지 기다린다. promise 가 처리가 끝나면 그 후에 결과를 반환한다.
예를들어, 3초 후 이행되는 프라미스를 예시로 사용하여 await가 어떻게 동작하는지 살펴보면
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 3000)
});
let result = await promise; // 프라미스가 이행될 때까지 기다림 (*)
alert(result); // 3초 후에 "완료!"
}
f(); // 실행
예제)
async function showAvatar() {
// JSON 읽기
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
// github 사용자 정보 읽기
let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
let githubUser = await githubResponse.json();
// 아바타 보여주기
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = "promise-avatar-example";
document.body.append(img);
// 3초 대기
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
img.remove();
return githubUser;
}
showAvatar();
참고블로그
'부트캠프 개발일지 2023-2024 > Bootcamp 생활기록' 카테고리의 다른 글
[4주차] 첫 슬럼프 (2) | 2023.10.23 |
---|---|
[3주차] JavaScript 개인과제: 검색기능 (TMDB API 데이터), 홈화면으로가기, 마우스이벤트 (0) | 2023.10.20 |
[3주차] JavaScript 개인과제: TMDB API 데이터 불러오기(fetch), 화면에 띄우기 +@ (1) | 2023.10.18 |
[3주차] 알고리즘 특강 (2) (0) | 2023.10.17 |
[3주차] 알고리즘 특강 (1) (0) | 2023.10.16 |