4 분 소요

🔮 동기 & 비동기

  • 용어 정리
    • 스레드 : 연산을 수행하는 일꾼 같은 역할.
    • 블로킹 작업 : 스레드가 한가지 일만 하고 다른 일을 할 수 없는 방식
    • 논블로킹 작업 : 하나의 작업을 하면서 다른 작업도 할 수 있는 방식 = 비동기 2번째 방식( 그냥 동시에 실행시키는 방식 )
    • 동기적 방식 : 지시 순서대로 작업을 수행하는 방식
    • 비동기 방식 : 멀티 쓰레드를 사용하거나 그냥 동시에 실행시키는 방식. 자바 스크립트의 경우 멀티 쓰레드 사용이 불가하므로 동시에 실행시키는 방식을 택한다.

📍 setTimeout() : 비동기 방식 사용하기

function taskA(a, b, cb) {
  setTimeout(() => {
    const res = a + b;
    cb(res);
  }, 3000);
}

taskA(3, 4, (res) => {
  console.log("A Task Result : " + res);
});
  • taskA : taskA라는 함수
  • a, b : 매개 변수
  • cb : 콜백 함수
  • setTimeout(() => {}, ms) : 동시 작업을 할 수 있도록 해줌. ms부분에는 몇 ms 뒤 계산된 값을 출력할 것인지 선택.

  • 실행 순서
    1. taskA(3, 4, f) 를 통해서 taskA 메소드를 호출
    2. a = 3, b = 4, cb = (res) => {console.log("A Task Result : " + res);} 매개 변수 연결. cb라는 함수( js는 딱히 데이터형을 정해주는 게 없기 때문에 이 부분이 헷갈림,,ㅜ 함순지, 변순지, 리턴이 있는지, 없는지,,등 여튼) 는 매개변수가 res이고 res를 출력해주는 함수이다.
    3. res는 뭐야? 현재 메인에서 taskA로 매개변수들이 넘어갔는데 거기서 나온 결과값이 cb함수의 인자가 된 것!
  • 🌗 taskA -> 인자 전달 -> res = a + b -> cb(res) -> 메인에 매개변수 res로 인자가 넘어감 -> 출력

📍비동기 방식 실행 방식

js 엔진에는 동기 방식인 경우 heap, CallStack 이 있다. 비동기 방식의 경우 Heap, CallStack, Callback Queue, Web API 로 나뉜다.

function taskA(a, b, cb) {
  setTimeout(() => {
    const res = a + b;
    cb(res);
  }, 3000);
}

taskA(3, 4, (res) => {
  console.log("A Task Result : " + res);
});
console.log("A code end");

>>>
A code end
A Task Result : 7
  1. 코드 실행 = CallStack에 MainContext가 들어감
  2. taskA() 메소드를 CallStack에 올림
  3. taskA() 메소드 안에 setTimeout() 메소드가 있음(cb()랑 같이) => 둘 다 CallStack에 올림
  4. setTimeOut, cb를 Web API로 넘겨 => 여기서 3초 기다려(setTimeout은 비동시 함수니까)
  5. 3초 기다리는 동안 taskA함수는 끝나서 CallStack에서 지워짐
  6. 3초가 지나면 setTimeout 메소드는 web API에서 지워지고 cb는 Callback Queue로 넘어옴
  7. Event Loop를 통해서 CallStack으로 cb메소드를 넘겨줌 => 실행
  8. cb 지워, main Context 지워.

📍 문제점

비동기 처리방식을 연결해서 처리해주고 싶다면 다음과 같이 콜백 지옥에 빠질 수 있음

taskA(4, 5, (a_res) => {
  console.log("A Result: ", a_res);
  taskB(a_res, (b_res) => {
    console.log("B Result: ", b_res);
    taskC(b_res, (c_res) => {
      console.log("C Result: ", c_res);
    });
  });
});

❗ 해결책 ❗
Promise 객체

🔮 Promise 객체 : 콜백 지옥 해결책

📍 콜백 지옥

function isPositive(number, resolve, reject) {
  setTimeout(() => {
    if (typeof number === "number") {
      //비동기 작업 성공 = resolve 상태
      resolve(number >= 0 ? "양수" : "음수");
    } else {
      //실패 = reject
      reject("주어진 값이 숫자형이 아닙니다.");
    }
  }, 2000);
}

isPositive(
  [],
  (res) => {
    console.log("성공적으로 실행됨 : ", res);
  },
  (err) => {
    console.log("실패 하였음 : ", err);
  }
);
  • isPositive() : 함수 이름
  • number : 매개 변수
  • resolve : 비동기 작업이 성공했을 때 실행되는 메소드
  • reject : 비동기 작업이 실패했을 때 실행되는 메소드

  • 메인 코드
    • [] 👉 number
    • (res) => console.log 👉 resolve : 즉 이 말은 resolve라는 메소드 이름이고, 구현부는 출력부분이다. 콘솔로그 앞에 있는 res는 매개변수이고 위에 isPositive 메소드에 있는 값은 인자이다.
  • 🌗 isPositive 메소드 호출 -> if 문 성립하면 resolve 메소드를 호출 -> 메인에 있는 resolve 실행. oo요딴식

📍 Promise 객체

  • 용어 정리

    • pending : 대기 상태
    • Fulfiled : 정상 완료 = resolve(해결)
    • Rejected : 실패 = reject(거부)

promise 객체는 비동기 작업을 하고, 그 작업의 결과를 promise로 반환 받는다. Promise는 비동기를 처리받는 함수로 만드는 것이다.

  • Promise 객체의 메소드
    • then() : resolve 수행이 된다면 그 결과를 then으로 전달
    • catch() : reject 수행 결과를 전달
  • 비동기 방식 활용 1.

    function isPositiveP(number) {
      //비동기 작업 수행 함수
      const executor = (resolve, reject) => {
        setTimeout(() => {
          if (typeof number === "number") {
            //비동기 작업 성공 = resolve 상태
            console.log(number);
            resolve(number >= 0 ? "양수" : "음수");
          } else {
            //실패 = reject
            reject("주어진 값이 숫자형이 아닙니다.");
          }
        }, 2000);
      };
      const asyncTask = new Promise(executor);
      return asyncTask; //promise 반환 = 비동기 작업을 하고, 그 작업의 결과를 promise로 반환받음
    }
    
    const res = isPositiveP(101);
    res
      .then((res) => {
        console.log("작업 성공");
      })
      .catch((err) => {
        console.log("error");
      });
    
    • executor : resolve 수행인지, reject 수행인지를 판단하는 함수
    • if 문 참 -> resolve 수행, resolve가 수행되므로 asyncTask는 fulFilled 상태이고 매개변수는 양수인 상태. fulFilled(정상 완료) 상태이므로 .then(res) 로 넘어감. res = 양수.
    • else 문 참 -> reject 수행, res = 주어진 값이 숫자형이 아닙니다. -> .catch 문 수행
    • ❗ 헷길리지만,,,resolve() 수행이 anyncTask에 2가지 값을 전달하는 느낌? main에서 res는 양수 를 리턴받는다. 하지만 isPositiveP의 리턴은 asyncTask 지만, resolve()가 실행이 된다면 정상 수행임을 인지(.then 사용), 리턴은 resolve 값 반환 -> 요런 느낌,,?
  • 비동기 방식 활용 2.
    function taskA(a, b) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          const res = a + b;
          resolve(res);
        }, 3000);
      });
    }
    

    이렇게 되면 taskA가 리턴하는 값은 정상 완료가 되었는지 아닌지이다. (예시는 일단 무조건 정상 완료를 가정하여 reject() 사용 X)

📍 async / await

  • async : 얘를 붙히면 Promise 객체 반환

    async function helloAsync() {
        return "hello Async";
    }
    
    console.log(helloAsync()); //promise 객체임
    
    >>> Promise { 'hello Async' }
    
  • await : 비동기 함수 호출 앞에 붙히면 동기 함수처럼 사용 가능.

태그:

카테고리:

업데이트:

댓글남기기