동기와 비동기 #2 callback, Promise, async/await

최정환·2022년 3월 11일
0

동기와 비동기

목록 보기
2/3

JS는 동기식 언어

JS는 하나의 작업이 끝난 후 다음 작업을 시작하며 코드가 작성된 순서대로 작동한다(Stack).

그럼 비동기로 JS를 다루기 위해서는 어떤 것을 사용해야 하나

CallBack

callback은 단순하게 말하면 다른 함수에 매개변수(parameter)로 넘겨준 함수를 말한다.
매개변수로 넘겨받은 함수를 사용할때가 되면 호출한다.

비동기식

console.log("지금의 나 안녕")

const callBack = () =>{
	console.log("5초 후의 나야 안녕");
}

setTimeout(callBack, 5000);	// 5초 후 callBack함수를 실행한다.

/*
지금의 나 안녕
..5초 후 
5초 후의 나야 안녕
*/

동기식

const go = (something) =>{
something()
}

const hello = ()=>{
	console.log("hello")
}

go(hello)	// hello	

비동기를 구현할 때 callback이 필요한 이유가 뭘까?

1. 특정코드가 끝나기 전 다른 코드가 실행되지 않게 하기 위해
2. 내가 원하는 시간에 코드가 작동하게 하고 싶을때 
3. 특정 메서드에서 필수적으로 콜백이 필요한 경우가 있다.


callback 지옥

콜백 함수를 익명으로 사용하는 과정이 반복되면서 가독성이 떨어지고 유지보수가 어려워지는 경우를 말한다.

setTimeout(
  (pin) => {
    let totalMoney = pin;
    console.log(totalMoney);

    setTimeout(
      (pin) => {
        totalMoney += pin;
        console.log(totalMoney);

        setTimeout(
          (pin) => {
            totalMoney += pin;
            console.log(totalMoney);

            setTimeout(
              (pin) => {
                totalMoney += pin;
                console.log(totalMoney);
              },
              300,
              1000,
            );
          },
          600,
          2000,
        );
      },
      900,
      3000,
    );
  },
  1200,
  4000,
);

0.3초마다 4000, 3000, 2000, 1000의 용돈을 받고 총 소지금을 출력함.

4000
7000
9000
10000

함수 하나가 끝나면 다음 함수를 실행한다.
비동기로 확실하게 작동한다. 하지만 코드가 너무 어려워진다.
함수가 어떤 역할을 하고 그에 대한 결과가 어떤식으로 나오는지 숙지가 되어있어야한다.

따라서
함수가 만약 오류를 return한다면 어떤 결과가 나올지 무섭다.
물론 하나하나 try catch를 사용해 분기처리를 해도 좋지만 여기서 분기처리를 나눈다면 더 지옥이 될 것이다.
유지 보수적인 부분에서 봐도 안좋다.

callback Hell 탈출 방법

1. 함수에게 이름을 주고 쪼갠다.
클린코드를 위해서는 이름이 있는 함수를 잘게 쪼개서 가독성을 높힐수 있다.

let totalMoney = 0;
const callBack = (pin) => {totalMoney += pin; return console.log(totalMoney)}

setTimeout(callBack, 1200, 4000);
setTimeout(callBack, 900, 3000);
setTimeout(callBack, 600, 2000);
setTimeout(callBack, 300, 1000);

/*
1000
3000
6000
10000
*/

2. Promise || await/async 사용



Promise

callback은 개념이지만 Promise는 JS객체이며 JS에서 비동기 구현을 위해 사용한다.

기본적으로 callback과 하는 일을 동일하다.

Promise의 세가지 상태

Pending(대기)

비동기 처리 로직이 아직 완료되지 않은 상태

라이브러리를 사용하면서 약속된 처리가 끝나기전 혹은 fetch GET 통신에서 JSON 상태로 바뀌기 전에 사용한다면 'Pending'이라는 문구를 나타낸다.

아직 약속된 처리가 진행되기 전에 접근하면 볼 수 있다.

Fulfilled(이행)

비동기 처리 로직이 수행완료되어 결과 값을 반환한 상태

Rejected(실패)

비동기 처리가 실패하거나 에러가 발생한 상태

fetch('url').then(res=>res.json()).then(json=>console.log(json))

// return Pending
fetch('url').then(res=>console.log(res))

url로 부터 데이터를 fetch 받을 때 자주 사용하는 코드다.
url에서 데이터를 받아온 후에 그 데이터를 json()을 한 후에 그 json을 사용할 수 있다.

만약 여기서 한 단계를 건너 뛴다면 Pending을 볼 수 있다.


Promise의 로직

객체 만들기

Promise 객체를 생성하는 시점부터 Pending 상태라고 볼 수 있다.
객체 안에는 callback 함수를 가지고 인자로 resolve, reject를 가지고 있다.


function getTen(){
  return new Promise(function(resolve, reject){
    resolve(10)
    reject(new Error("Request Rejected"))
  })
}

getTen().then(v=>conosle.log(v)).catch(err=>console.log(err)) // 10
getTen().then(()=> {throw new Error("error!!")}).catch(err=>console.log(err)) // Error: error!!

resolve
호출된다면 Pending 상태에서 Fulfilled 상태로 넘어간다.
즉 다음의 .then으로 이어진다.

reject
호출된다면 Rejected 상태로 넘어간다.
코드에 작성된 catch로 이어진다.


async/await

비동기 처리 패턴 중 최근에 나온 문법.
callback과 promise의 단점을 보완하고 가독성이 좋아졌다.

1. 콜백
함수(()=>함수(()=>함수(()=>함수())))

2. Promise
함수().then().catch()

3. async/await
const 함수 = async() =>{
	await 비동기_처리해야하는_함수();
}

사용하는 예

const data = async() =>{
	const json = await fetch(url).then((response)=>response.json());
  	const {id, name} =  json;
	console.log(id, name)
}
  1. 함수 시작전에 async 라는 키워드를 사용해야한다. => 언제나 Promise 반환
  2. 비동기 처리 부분 앞에 await 이라는 키워드를 사용해야한다.

에러 핸들링

try~catch를 사용한다.

const data = async() =>{
	try{
     	const {id, name} = await fetchData(url)
		return console.log(id, name)
    }
  	catch(err){
    	console.log(err)
  } 
}

try : 스코프에 있는 작업을 수행한다. 만약에 에러가 나면 catch로 보낸다.
catch : 인자에 error를 받고 스코프 안에 있는 작업을 수행한다.


⭐️ await async 중요점

1️⃣ async

함수 작성시 async을 붙인다면 무조건 Promise가 resolve된 상태를 return한다.
=> async가 붙는다면 Promise가 아닌 값을 반환하더라도 resolved promise로 값을 감싸 이행된 Promise가 반환되도록한다.

2️⃣ awiat

  • awiat은 promise가 처리될 때까지 기다린다.
  • 일반 함수(async가 없는)에는 사용이 불가하다.
  • 최상위 레벨 코드에서는 작동하지 않는다.
  • await는 thenable 객체를 받는다.


https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise

0개의 댓글