개인과제 재제출하면서 최종목표였던 비동기작업..!
맨날 기본 비동기 기본 구문만 가지고 연습하다가 실제로 적용해보려니까 어디서부터 손을 봐야할지 전혀 모르겠어서 울고싶었다 😭
팀 도움을 받아서 끙차 해결하긴했는데 fetch
라든가 Promise
도 흐름을 파악하지 못하고 외우다시피 쓰는 느낌이라서 조금 더 꼼꼼하게 공부해보았다.
fetch api
api를 받아오고 받아온 데이터를 활용해서 무언가를 만드는 일이 정말 많고 일상이 될 것 같았다. 단순히 외워서 써도 되는데 fetch
가 함수인지 뭔지도 모르고 따라 쓰려니까 머리에 들어오지를 않더라..ㅎ
그래서 mdn도 보고 관련 강의도 찾아서 정리했다.
구문
fetch(resource)
fetch(resource, options)
fetch
를 사용하기위해 작성하는 구문은 이렇게 쓰면 된다.
resource
에는 주로 우리가 데이터를 받아올 api 주소
가 들어간다.
실제 활용 예시
fetch("https://jsonplaceholder.typicode.com/posts")
.then((response) => {
return response.json(); // 위 주소로 받아온 데이터 타입이 json 이라는 걸 알기 위해 return 값 json으로 처리
})
.then((myJson) => { // 우리가 가져온 데이터는 여기에서 알 수 있다.
console.log(myJson);
})
(➕ api 주소는 연습할 때 사용하면 좋은 가짜api(?)사이트에서 가져왔다. : https://jsonplaceholder.typicode.com/)
fetch
는 함수인데, 이 뒤에 주소를 주고 실행을 하면 파라미터
(여기서는 myJson)를 통해 웹서버가 return
해준다. 이 데이터들은 json형태
인데 자바스크립트 타입에 맞게 컨버팅 해주는 결과를 가져올 수 있게 된다.
따라서 위 내용은 1) fetch
뒤에 있는 url
주소에서 데이터를 가져오면, 2)json
타입으로 바꿔주고, 3) 그러고 나서 myJson이라는 파라미터
에 전달해줘!가 된다.
놀라운(?) 사실은 ⭐️ 위에서 사용한 .then
메소드는 Promise
형태이다.
.then
이 Promise
를 내뱉기 때문에 배열 메소드를 체이닝해서 썼던 것처럼, 똑같이 Promise
메소드를 체이닝해서 쓸 수 있다.(Promise chaining
)
구문
fetch(resource)
fetch(resource, options)
const fetchResponsePromise = fetch(resource[, init])
위에서 본 내용에 조금 더 추가해보았다.
fetch
함수를 실행하면 resource
를 주고 위에서 본 것처럼 여기에 url
을 주면 된다.
mdn공식문서에서 보면 위 문구를 확인할 수 있는데 "Response 객체로 이행하는 Promise입니다." 라는 말이다. 즉, fetch
함수는 Promise
데이터 타입을 return
하고, Promise
데이터 타입은 Response Object
타입(객체)을 올려준다.
예시
fetch("https://jsonplaceholder.typicode.com/posts")
.then((response) => {
// console.log('response', response.json());
return response.json();
})
.catch((reject) => {
console.log(reject);
})
.then((data) => {
console.log('data', data); // Promise chaining
})
코드를 먼저 보도록하자
fetch
의 주소는 Promise
를 return
해서 비동기적
으로 처리할 가능성이 높다..then
, .catch
>> 둘다 콜백함수를 받는다.resolve
, reject
)이 코드를 실행시켜 확인해보면
fetch Promise
로 pending
상태라고 뜨는 걸 보면서 우리는 Promise
데이터를 return
한다는 말을 이해할 수 있다.
이렇게 json
타입으로 컨버팅 된 데이터들이 Response
객체 안에 데이터가 담긴걸 확인 할 수 있다.
객체타입으로 데이터가 불러와졌기 때문에 우리는 이를 활용해서 필요한 데이터를 뽑아서 사용할 수 있다.
fetch
에서 계속 등장한 Promise
! 자주 등장했지만 이해도가 부족한 것 같아 정리하면서 다시 공부해보자,,,
예시
function timer(time) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(time);
}, time);
});
}
Promise
예시로 너무나 많이 등장하는 setTimeout
..🫠
이번에도 역시나 이 함수를 이용해서 timer
라는 함수를 만들었다.
이 함수는 Promise
값을 반환하는데 time
이라는 인자에 값을 받아서 그만큼 뒤에 결과를 보여준다.
이제 이 함수를 조금더 간략하게 콜백지옥을 막는 코드로 바꿔보자.
Promise 메소드 사용하기
fetch
정리할 때 말했었는데 Promise
를 반환하는 메소드가 2개 있었다. 바로 .then
과 .catch
!
이 두 메소드로 Promise chaining
해서 작성하면 아래와 같다.
console.log("START")
timer(1000).then((time) => {
console.log('time: ' + time);
// 기존 시간에 1초 더한 만큼 timer 굴리기
return timer(time + 1000); // promise로 return 하니까 then 이을 수 있음.
}).then((time) => {
console.log('time: ' + time);
return timer(time + 1000);
}).then((time) => {
console.log('time: ' + time);
});
console.log("END")
여기에 timer
가 실행되기 전에는 start가 콘솔에 찍히고, 끝나면 end 문구가 찍히도록 코드를 추가했다.
✅ 콘솔 확인
띠용용👀
이것은 내가 원한 결과가 아닌디용...
timer
는 Promise
니까 비동기적으로 실행된다.
반면에 console.log
으로 작성한 start와 end는 비동기로 실행되는 코드가 아니다.
따라서 console.log("START")
가 1번으로 실행되고 -> timer
는 비동기 함수니까 일단 실행되는 동안 -> console.log("END")
실행이 된다. -> 그 다음 실행이 완료된 timer
가 찍히는 순서이기 때문에 저런 결과가 나온 것이다.
이렇게 수정해주면? 원하는 결과를 얻을 수 있게 된다.
자 이제 똑같은 코드를 async/await
으로 고쳐보자.
꼭 알아두어야하는 사항 2가지!
1. await
은 비동기로 실행되는 것 앞에 붙여주기.
2. await
는 async
안에서만 사용이 가능하므로 function
앞에 async
를 써서 만들어주기!
이를 토대로 만든 코드는?!
async function run() {
console.log("START")
let time = await timer(1000);
/* then 안에 있는 첫번째 파라미터를 받아오는 방법, await를 써서 비동기라고 표시*/
console.log('time: ' + time);
time = await timer(time + 1000);
console.log('time: ' + time);
time = await timer(time + 1000);
console.log('time: ' + time);
console.log("END")
}
run();
//함수니까 꼭 실행시켜줘야만 결과를 얻을 수 있다!
async
/await
로 바꾸기 전에 promise
, then
을 사용했던 코드에 있던 첫번째 파라미터 time
을 받아오는 방법은 let time
으로 지정해서 사용한다.
이렇게 적어주면 2번에서 then
메소드를 썼던 코드와 동일한 결과를 받을 수 있다.
늘 느끼지만 예시코드들은 너무나 이해가 잘 되고 쉽게 느껴진다ㅋㅋㅋ 문제는 실제로 적용해보려고 하거나 조금만 변형된 예시들을 만나면 에러가 뜬다는고지..ㅜ
달리기반 실습에서 비동기 관련 문제들을 풀었는데 그것도 복습하면서 오늘 정리한 내용이랑 같이 TIL로 남겨놓아야겠다!
리액트 들어가기 전까지 비동기 쪼랩 탈출하자🐣