211116_개발자 준비하기(45일차) - 비동기 호출

주형(Jureamer)·2022년 1월 4일
0
post-custom-banner

배운 것(끄적끄적)


- 비동기 호출이란?

  • 비동기 호출 사례

Untitled

** 커피 주문 할 때를 생각 해본다면
(동기)
1번째 손님이 주문하고, 바리스타가 음료를 만들고(처리), 음료를 받은 다음에
2번째 손님이 주문할 수 있는 상태가 된다., 순서가 될 때까지 뒤에 있는 사람은 무한정 기다릴 수 밖에 없는 것이다.

(비동기)
1번째 손님이 주문하고, 바리스타가 음료를 만들 동안, 2번째 손님이 주문하고, 바리스타가 만들 준비를 하고,
3번째 손님이 주문하고...를 반복하는게 비동기적인 방식이다.

병렬과도 비슷한 방식이라고 생각하는데 오래 걸리는 작업이 끼어든다면 비동기 방식으로 처리하는 게
효율적임을 알 수 있다.

** 전화(동기)문자(비동기)의 차이
 - 전화는 현재 하는 동작을 멈추고(blocking) 요청에 대한 결과가 동시에 일어난다. (sync)
 - 문자는 나중에 확인 할 수 있고(non-blocking) 요청에 대한 결과가 동시에 일어나지 않음 (async)

Untitled

비동기 호출 사용법

  • 콜백 메소드 이용

  • setInterval(callback, millisecond) ⇒ clearInterval(timerId) 로 삭제 가능

setInterval(function() {
console.log("1초마다 실행");, 1000}; // "1초마다 실행", "1초마다 실행" ...

const timer = setInterval(function() {
console.log("1초마다 실행");, 1000}; // "1초마다 실행", "1초마다 실행" ...

clearInterval(timer);
  • setTimeout(callback, millisecond) ⇒ clearTimeout으로 삭제 가능
setTimeout(function () {
  console.log('1초 후 실행');
}, 1000);
// 123
  • Promise
    • Promise에 포함된 메소드(.all, .race, .reject, .resolve)

    • Promise의 상태

      • 대기(Pending): 이행하거나 거부되지 않은 초기 상태
      • 이행(Fullfilled): 연산이 성공적으로 완료됨
      • 거부(Rejected): 연산이 실패함
    • 사용법: 아래와 같이 then과, catch를 통해 이행된 결과(data) 혹은 실패(reason) 값을 반환하여 사용할 수 있다.

      (... 생략)
      
      const sleep = (wait) => {
        return new Promise((resolve) => {
          setTimeout(() => {
            resolve("hello");
          }, wait);
        });
      };
      
      function runPromise() {
        resetTitle();
        playVideo();
        sleep(1000)
          .then(
            (param) => {
              console.log(param), pauseVideo();
              displayTitle();
              return "world";
            }
            // (param2) => {
            //   console.log(param2);
            //   return "Error (1)";
            // } //hello가 찍힘
          )
          // .then(sleep.bind(null, 500))
          .then((param) => {
            console.log(param); // world가 찍힘
            // sleep(500);
          })
          .then(highlightTitle)
          .then(sleep.bind(null, 1000))
          .then(resetTitle)
          .catch(() => {
            console.log("Error (2)");
          });
      }

      *** Then(successCallback, failureCallback)

      *** Catch(failureCallback) ⇒ then(null, failurCallback)의 축약임.

      doSomething()
      .then(result => doSomethingElse(result))
      .then(newResult => doThirdThing(newResult))
      .then(finalResult => {
        console.log(`Got the final result: ${finalResult}`);
      })
      .catch(failureCallback);

      *** Chaining: 비동기 작업이 순차적으로 이루어져야할 때 promise chain을 사용한다.

      //콜백 지옥의 예시
      doSomething(function(result) {
        doSomethingElse(result, function(newResult) {
          doThirdThing(newResult, function(finalResult) {
            console.log('Got the final result: ' + finalResult);
          }, failureCallback);
        }, failureCallback);
      }, failureCallback);
      
      // Promise Chain을 이용
      
      doSomething().then(function(result) {
        return doSomethingElse(result);
      })
      .then(function(newResult) {
        return doThirdThing(newResult);
      })
      .then(function(finalResult) {
        console.log('Got the final result: ' + finalResult);
      })
      .catch(failureCallback);
    • Promise 에러처리는 가급적 Catch()를 사용한다.

      // then()의 두 번째 인자로는 감지하지 못하는 오류
      function getData() {
        return new Promise(function(resolve, reject) {
          resolve('hi');
        });
      }
      
      getData().then(function(result) {
        console.log(result);
        throw new Error("Error in then()"); // Uncaught (in promise) Error: Error in then()
      }, function(err) {
        console.log('then error : ', err);
      });

      resolve 값을 정상적으로 받았지만 then 구문에서 오류가 나는 경우

Untitled

  Uncaught에러를 뱉으면서 정상적으로 처리가 되지 않는다. 이를 방지하기 위해 catch()를 사용하며, 더 많

  은 예외 처리 상황을 방지 하기 위해 then의 마지막에 catch를 사용하는게 좋다.
  • async / await

async/await은 비동기 처리 패턴 중 가장 최근에 나온 방식이다.(ECMAScript2017)

  • 함수 앞에 async를, 비동기 호출을 사용하고 싶은 메소드 앞에 await을 붙여준다.
// async를 함수 앞에 선언해줌으로써 promise 반환하게 되었다.
async function hello() { return "Hello" };
hello();

let hello = async () => { return "Hello" }; // 화살표로 사용할 때
=> // 결괏값: Promise {<fulfilled>: 'Hello'}

// async를 선언할 때 메소드 앞에 await을 붙여주게 되면 정상 작동
async function hello() { return "Hello" };
await hello(); 
=> // 결괏값: "Hello"

Reference

https://joshua1988.github.io/web-development/javascript/promise-for-beginners/

MDN Promise

https://developer.mozilla.org/ko/docs/Learn/JavaScript/Asynchronous/Async_await

느낀점


얼마 전 리액트 과제 때 렌더링 때문에 문제를 안풀려서 정보를 찾다가 비동기 방식에 대해서 얼핏 본 적이 있었다. 그땐 어렴풋이 어떻게 동작하는구나~라고 이해하고 넘어갔었는데 직접 배우고 사용해보니 서버와 정보를 주고 받을 때 핵심적인 기능이라는 것을 깨달았다. 최근 몇년 사이에도 async-await이라는 기능이 나올 정도로 중요하고 많이 편리한 기능인 만큼 잘 배워서 써야겠다고 생각된다.

내일 배울 것


  • 비동기 async~await
  • fetch API
  • Event Loop
profile
작게라도 꾸준히 성장하는게 목표입니다.
post-custom-banner

0개의 댓글