2022년 10월 25일
이론JS
조회 : 333|3분 읽기
비동기 callback, Promise, async/await
JS는 동기식 언어
JS는 하나의 작업이 끝난 후 다음 작업을 시작하며 코드가 작성된 순서대로 작동한다(Stack).
그럼 비동기로 JS를 다루기 위해서는 어떤 것을 사용해야 하나
CallBack
callback은 단순하게 말하면 다른 함수에 매개변수(parameter)로 넘겨준 함수를 말한다.
매개변수로 넘겨받은 함수를 사용할때가 되면 호출한다.
비동기식
javascript1console.log("지금의 나 안녕") 2 3const callBack = () =>{ 4 console.log("5초 후의 나야 안녕"); 5} 6 7setTimeout(callBack, 5000); // 5초 후 callBack함수를 실행한다. 8 9/* 10지금의 나 안녕 11..5초 후 125초 후의 나야 안녕 13*/
동기식
javascript1const go = (something) =>{ 2something() 3} 4 5const hello = ()=>{ 6 console.log("hello") 7} 8 9go(hello) // hello
비동기를 구현할 때 callback이 필요한 이유가 뭘까?
1. 특정코드가 끝나기 전 다른 코드가 실행되지 않게 하기 위해
2. 내가 원하는 시간에 코드가 작동하게 하고 싶을때
3. 특정 메서드에서 필수적으로 콜백이 필요한 경우가 있다.
callback 지옥
콜백 함수를 익명으로 사용하는 과정이 반복되면서 가독성이 떨어지고 유지보수가 어려워지는 경우를 말한다.
javascript1setTimeout( 2 (pin) => { 3 let totalMoney = pin; 4 console.log(totalMoney); 5 6 setTimeout( 7 (pin) => { 8 totalMoney += pin; 9 console.log(totalMoney); 10 11 setTimeout( 12 (pin) => { 13 totalMoney += pin; 14 console.log(totalMoney); 15 16 setTimeout( 17 (pin) => { 18 totalMoney += pin; 19 console.log(totalMoney); 20 }, 21 300, 22 1000, 23 ); 24 }, 25 600, 26 2000, 27 ); 28 }, 29 900, 30 3000, 31 ); 32 }, 33 1200, 34 4000, 35);
0.3초마다 4000, 3000, 2000, 1000의 용돈을 받고 총 소지금을 출력함.
4000
7000
9000
10000
함수 하나가 끝나면 다음 함수를 실행한다.
비동기로 확실하게 작동한다. 하지만 코드가 너무 어려워진다.
함수가 어떤 역할을 하고 그에 대한 결과가 어떤식으로 나오는지 숙지가 되어있어야한다.
따라서
함수가 만약 오류를 return한다면 어떤 결과가 나올지 무섭다.
물론 하나하나 try catch를 사용해 분기처리를 해도 좋지만 여기서 분기처리를 나눈다면 더 지옥이 될 것이다.
유지 보수적인 부분에서 봐도 안좋다.
callback Hell 탈출 방법
1. 함수에게 이름을 주고 쪼갠다.
클린코드를 위해서는 이름이 있는 함수를 잘게 쪼개서 가독성을 높힐수 있다.
javascript1let totalMoney = 0; 2const callBack = (pin) => {totalMoney += pin; return console.log(totalMoney)} 3 4setTimeout(callBack, 1200, 4000); 5setTimeout(callBack, 900, 3000); 6setTimeout(callBack, 600, 2000); 7setTimeout(callBack, 300, 1000); 8 9/* 101000 113000 126000 1310000 14*/
2. Promise || await/async 사용
Promise
callback은 개념이지만 Promise는 JS객체이며 JS에서 비동기 구현을 위해 사용한다.
기본적으로 callback과 하는 일을 동일하다.
Promise의 세가지 상태
Pending(대기)
비동기 처리 로직이 아직 완료되지 않은 상태
라이브러리를 사용하면서 약속된 처리가 끝나기전 혹은 fetch GET 통신에서 JSON 상태로 바뀌기 전에 사용한다면 'Pending'이라는 문구를 나타낸다.
아직 약속된 처리가 진행되기 전에 접근하면 볼 수 있다.
Fulfilled(이행)
비동기 처리 로직이 수행완료되어 결과 값을 반환한 상태
Rejected(실패)
비동기 처리가 실패하거나 에러가 발생한 상태
javascript1fetch('url').then(res=>res.json()).then(json=>console.log(json)) 2 3// return Pending 4fetch('url').then(res=>console.log(res))
url로 부터 데이터를 fetch 받을 때 자주 사용하는 코드다.
url에서 데이터를 받아온 후에 그 데이터를 json()을 한 후에 그 json을 사용할 수 있다.
만약 여기서 한 단계를 건너 뛴다면 Pending을 볼 수 있다.
Promise의 로직
객체 만들기
Promise 객체를 생성하는 시점부터 Pending 상태라고 볼 수 있다.
객체 안에는 callback 함수를 가지고 인자로 resolve, reject를 가지고 있다.
javascript1 2function getTen(){ 3 return new Promise(function(resolve, reject){ 4 resolve(10) 5 reject(new Error("Request Rejected")) 6 }) 7} 8 9getTen().then(v=>conosle.log(v)).catch(err=>console.log(err)) // 10 10getTen().then(()=> {throw new Error("error!!")}).catch(err=>console.log(err)) // Error: error!!
resolve
호출된다면 Pending 상태에서 Fulfilled 상태로 넘어간다.
즉 다음의 .then으로 이어진다.
즉 다음의 .then으로 이어진다.
reject
호출된다면 Rejected 상태로 넘어간다.
코드에 작성된 catch로 이어진다.
코드에 작성된 catch로 이어진다.
async/await
비동기 처리 패턴 중 최근에 나온 문법.
callback과 promise의 단점을 보완하고 가독성이 좋아졌다.
javascript11. 콜백 2함수(()=>함수(()=>함수(()=>함수()))) 3 42. Promise 5함수().then().catch() 6 73. async/await 8const 함수 = async() =>{ 9 await 비동기_처리해야하는_함수(); 10}
사용하는 예
javascript1const data = async() =>{ 2 const json = await fetch(url).then((response)=>response.json()); 3 const {id, name} = json; 4 console.log(id, name) 5}
- 함수 시작전에 async 라는 키워드를 사용해야한다. => 언제나 Promise 반환
- 비동기 처리 부분 앞에 await 이라는 키워드를 사용해야한다.
에러 핸들링
try~catch를 사용한다.
javascript1const data = async() =>{ 2 try{ 3 const {id, name} = await fetchData(url) 4 return console.log(id, name) 5 } 6 catch(err){ 7 console.log(err) 8 } 9}
try : 스코프에 있는 작업을 수행한다. 만약에 에러가 나면 catch로 보낸다.
catch : 인자에 error를 받고 스코프 안에 있는 작업을 수행한다.
catch : 인자에 error를 받고 스코프 안에 있는 작업을 수행한다.
⭐️ await async 중요점
1️⃣ async
함수 작성시 async을 붙인다면 무조건 Promise가 resolve된 상태를 return한다.
=> async가 붙는다면 Promise가 아닌 값을 반환하더라도 resolved promise로 값을 감싸 이행된 Promise가 반환되도록한다.
=> async가 붙는다면 Promise가 아닌 값을 반환하더라도 resolved promise로 값을 감싸 이행된 Promise가 반환되도록한다.
2️⃣ awiat
- awiat은 promise가 처리될 때까지 기다린다.
- 일반 함수(async가 없는)에는 사용이 불가하다.
- 최상위 레벨 코드에서는 작동하지 않는다.
- await는 thenable 객체를 받는다.
결론
callback, promise의 차이점에 대한 글이 많았고 await async 를 어떨때 사용하냐는 질문보단 이게 뭐냐에 대한 질문에 대해서 자세히 알아보기 위해서 정리해보았다.
결국 자바스크립트에서 대격변이 일어난 es6에서 부터 promise - await/async 를 사용해 콜백을 줄이게 되었다는 얘기 밖에 없었고 근본적으로 callback과 promise의 차이점은 코드의 가독성, 유지보수 용이를 좋게 할 수 있다는 것이었다.
거창해보이진 않지만 결국 코드를 작성하는데 있어서 가독성과 유지보수 용이는 가장 중요한 부분이라는 것을 다시 한번 알게 되었다.
거창해보이진 않지만 결국 코드를 작성하는데 있어서 가독성과 유지보수 용이는 가장 중요한 부분이라는 것을 다시 한번 알게 되었다.