이전에 공부하면서 어렴풋이 알기만 하고 넘어갔던 Promise와 async/await과 조금 더 친해지는 계기가 되었다.
비동기적인 처리를 동기적으로 제어하기위해 callback을 사용했는데 이를 잘못 사용하게 되면 뭐가 뭔지 알아보기 힘들 정도로 callback을 반복하게 되고 코드가 지옥에 빠져버리는 모양이 되어버린다.
지옥에 빠진 코드를 구원하기 위해 Promise가 등장했다.
Promise는 resolve와 reject를 양손에 들고 태어났다.
resolve는 특정 목적을 달성한 뒤에 다음 실행할 함수에게 넘어갈 수 있도록 해준다. 마치 이어달리기의 바톤 같은 느낌.
resolve는 특정 값을 함께 넘겨줄 수도 있는데 이것을 이어받는 것은 then() 이다. 이어달리기에서 다음주자인 것이다. 그렇다면 then도 할일을 마치면 다음 주자인 then에게 바톤을 넘겨줘야 한다. 이때는 return을 사용한다.
선수가 뛰다보면 넘어져서 경기를 계속할 수 없을 수도 있다. 이때 사용되는 것이 reject(). 백기를 들어버린다. then().then(). ... 하며 이어지는 주자들의 끝에는 .catch()가 있는데 reject를 사용하면 바로 catch로 넘어가는 것이다.
const runner = () => {
return new Promise( (resolve, reject) => {
if (넘어져서 다리가 부러졌다){
reject("GG!");
}
resolve("바톤 넘겨!");
}
}
const running = () => {
runner()
.then((바톤1)=>{
return 바톤1;
})
.then((바톤2)=>{
return 바톤2;
})
.then((바톤3)=>{
console.log("완주!");
.catch((기권)=>{
console.log(기권);
})
}
이런 느낌적인 느낌.
하지만 콜백 지옥에 나타난 구세주 Promise도 지옥에 빠져버리는 일이 생기기도 했다.
callback : "구하러 왔구나!"
Promise : "아니 나도 잡혔어"
그래서 나타난 async / await
예전에 봤을 때는 사실 이들의 굉장함을 알지 못했다. 그냥 기다려주는구나, 써먹을데가 많겠구나 정도만 느끼며 사실 제대로 된 사용법도 감을 잡지 못했었다.
그런데 오늘 콜백 지옥과 Promise.then.then.then.... 을 반복하다가 async / await 을 사용해보니 그는 진정한 구원자의 기운을 내뿜고 있었다.
const running = async () => {
const run1 = await runner();
const run2 = await runner();
const run3 = await runner();
}
then으로 길게 늘어지던 코드가 위 코드처럼 보기 좋게 정리가 된다. 사실 제대로 다 변환시킨 것은 아니지만 그런 느낌이라는 것.
그런데 Promise가 웃긴게 기껏 비동기처리 순서 제어하려고 만들어놓고 Promise를 한꺼번에 처리하는 Promise.all이라는 것을 만들었다.
Promise.all(
[somethingPromise(),
somethingPromise(),
somethingPromise()])
.then( (values) => { ... } )
이런 식으로 사용하는데 all() 안에는 프로미스를 담은 배열이 들어가고 각각의 프로미스들의 반환 값을 values라는 배열에 담아서 되돌려준다. 비동기 순서 제어를 하다가 갑자기 또 비동기적으로 처리해야할 때 필요한 모양이다.
fetch에 대해서도 배웠는데 이것 역시 알고는 있었지만 제대로 쓰는 법은 몰랐던 녀석이다.
URL을 통한 API 요청을 도와주는데 fetch(URL).then() ... 과 같이 Promise의 형식으로 이루어져있다.
그리고 보통 URL을 통한 API 요청을 하면 돌아오는 결과 값이 stringify된 문자열로 되어있기 때문에 JSON.parse를 해줄 필요가 있다. 다만 .json() 메소드가 자체적으로 있기 때문에 이를 사용한다.
fetch(url)
.then((response)=>response.json())
.then((json)=>console.log(json))
.catch((error) => console.lop(error));