2024.01.17 TIL - 동기와 비동기

김민석·2024년 1월 17일
0

TIL

목록 보기
16/78
post-thumbnail

동기와 비동기

  1. 동기 : synchronous
    a. 현재 실행중인 코드가 끝나야 다음 코드를 실행하는 방식을 말함!
    b. CPU의 계산에 의해 즉시 처리가 가능한 대부분의 코드는 동기적 코드
    c. 계산이 복잡해서 CPU가 계산하는 데에 오래 걸리는 코드 역시도 동기적 코드
  2. 비동기 : a + synchronous ⇒ async라고들 흔히 부름
    a. 실행 중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어가는 방식
    b. setTimeout, addEventListner 등
    c. 별도의 요청, 실행 대기, 보류 등과 관련된 코드는 모두 비동기적 코드
  3. 웹의 복잡도가 올라갈 수록 비동기적 코드의 비중이 늘어난다!

비동기 작업의 동기적 표현

  1. Promise
  2. Generator
  3. async / await

(강의자료)

Promise

Promise는 비동기 처리에 대해, 처리가 끝나면 알려달라는 ‘약속’이에요.

  • new 연산자로 호출한 Promise의 인자로 넘어가는 콜백은 바로 실행돼요.
  • 그 내부의 resolve(또는 reject) 함수를 호출하는 구문이 있을 경우 resolve(또는 reject) 둘 중 하나가 실행되기 전까지는 다음(then), 오류(catch)로 넘어가지 않아요.
  • 따라서, 비동기작업이 완료될 때 비로소 resolve, reject 호출해요.
let myFirstPromise = new Promise((resolve, reject) => {
  // 우리가 수행한 비동기 작업이 성공한 경우 resolve(...)를 호출하고, 
  // 실패한 경우 reject(...)를 호출한다.
  // 이 예제에서는 setTimeout()을 사용해 비동기 코드를 흉내낸다.
  setTimeout(function () {
    resolve("성공!"); // 문제 없음!
  }, 250);
});
myFirstPromise.then((successMessage) => {
  // successMessage는 위에서 resolve(...) 호출에 제공한 값.
  // 위에서 문자열을 줬으니 아마 문자열일 것이다.
  console.log("와! " + successMessage); // 와! 성공!
});

Generator

*가 붙은 함수가 제너레이터 함수입니다. 제너레이터 함수는 실행하면, Iterator 객체가 반환(next()를 가지고 있음)돼요.

iterator 은 객체는 next 메서드로 순환 할 수 있는 객체구요. next 메서드 호출 시, Generator 함수 내부에서 가장 먼저 등장하는 yield에서 stop 이후 다시 next 메서드를 호출하면 멈췄던 부분 -> 그 다음의 yield까지 실행 후 stop

즉, 비동기 작업이 완료되는 시점마다 next 메서드를 호출해주면 Generator 함수 내부소스가 위 -> 아래 순차적으로 진행돼요 😊

function* generator() {
  yield 1;
  yield 2;
  yield 3;
}
const gen = generator(); // "Generator { }"
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3

async / await

ES2017에서 새롭게 추가된 async/await 문을 이용했어요. 비동기 작업을 수행코자 하는 함수 앞에 async 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await를 붙여주면 된답니다.

Promise ~ then과 동일한 효과를 얻을 수 있어요

function resolveAfter2Seconds() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}
async function asyncCall() {
  console.log('calling');
  const result = await resolveAfter2Seconds();
  console.log(result);  // Expected output: "resolved"
}
asyncCall();

Promise를 async/await으로 리팩토링

promise를 사용한 코드를 async를 사용한 코드로 바꿔줄 수 있다. 아래 예시를 보자.

function getProcessedData(url) {
  return downloadData(url) // returns a promise
    .catch((e) => {
      return downloadFallbackData(url); // returns a promise
    })
    .then((v) => {
      return processDataInWorker(v); // returns a promise
    });
}

위 코드는 아래로 변경이 가능하다.

async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url);
  } catch (e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}

위 예제에서는 return 구문에 await 구문이 없는데,
이는 async function의 반환값이 암묵적으로 Promise.resolve로 감싸지기 때문이다.

profile
화이팅 화이팅

0개의 댓글