42장 비동기 프로그래밍

42.1 동기 처리와 비동기 처리(42-01)

  • 실행 컨텍스트 스택에서 foo함수 실행컨텍스트 push하고 pop하고 bar함수가 동일하게 동작
const foo = () => {};
const bar = () => {};

foo();
bar();

42-02

  • 싱글 스레드로 방식 하기 때문에 처리 시간이 좀 걸리는 일을 하면 블로킹(작업중단)이 발생 - 이 같은 방식이 동기처리
// sleep 함수는 일정 시간(delay)이 경과한 이후에 콜백 함수(func)를 호출한다.
function sleep(func, delay) {
  // Date.now()는 현재 시간을 숫자(ms)로 반환한다.("30.2.1. Date.now" 참고)
  const delayUntil = Date.now() + delay;

  // 현재 시간(Date.now())에 delay를 더한 delayUntil이 현재 시간보다 작으면 계속 반복한다.
  while (Date.now() < delayUntil);
  // 일정 시간(delay)이 경과한 이후에 콜백 함수(func)를 호출한다.
  func();
}

function foo() {
  console.log('foo');
}

function bar() {
  console.log('bar');
}

// sleep 함수는 3초 이상 실행된다..
sleep(foo, 3 * 1000);
// bar 함수는 sleep 함수의 실행이 종료된 이후에 호출되므로 3초 이상 블로킹된다.
bar();
// (3초 경과 후) foo 호출 -> bar 호출

42-03

  • 블로킹하지 않고 곧바로 실행하는 방식이 - 비동기 처리
function foo() {
  console.log('foo');
}

function bar() {
  console.log('bar');
}

// 타이머 함수 setTimeout은 일정 시간이 경과한 이후에 콜백 함수 foo를 호출한다.
// 타이머 함수 setTimeout은 bar 함수를 블로킹하지 않는다.
setTimeout(foo, 3 * 1000); // 비동기 함수임
bar();
// bar 호출 -> (3초 경과 후) foo 호출

42.2 이벤트 루프와 태스크 큐(42-04)

  • 자바스크립트 엔진은 콜 스택(실행 컨텍스트 스택), 힙(실행 컨텍스트가 참조할 객체가 저장됨)으로 구성

  • 브라우저 환경은 이벤트 루프(콜 스택 비었고 테스크 큐에 대기중 함수 있다면 대기중 함수 콜 스택으로 이동 시키고 실행), Web API, 테스크 큐(콜백 함수 저장)로 구성

  • 브라우저는 심지어 멀티 스레드이며, 자바스크립트 엔진과 브라우저가 서로 상호작용해서 비동기 처리 방식을 구현 가능하게 됨

  • 아래 예제의 흐름을 보면 내부적인 동작 방식을 이해할 수 있다

  • 1.전역 코드 평가되어 전역 실행 컨텍스트 생성 및 콜 스택에 푸시 2.전역 코드 실행으로 setTimeout함수 호출. 함수도 함수 실행 컨텍스트 생성 및 콜 스택 푸시되어 현재 실행 중 상태. 브라우저의 Web API인 타이머 함수도 똑같이 함수 실행 컨텍스트 생성 3.setTimeout함수 실행시 콜백 함수 호출 스케줄링하고 종료. 즉, 콜 스택에서 팝. 이때 호출 스케줄링, 즉 타이머 설정과 타이머가 만료되면 콜백 함수를 테스트 큐에 푸시하는 것은 브라우저의 역할 4.(브라우저4-1과 자바스크립트 엔진4-2는 병행 처리된다) 4-1.브라우저는 타이머 설정후 만료를 기다림. 만료되면 콜백함수 foo가 테스크 큐에 푸시. 최소 지연 시간 4ms라서 0초 딜레이여도 4ms는 기다림. 콜백 함수는 정확히 지연 시간 후에 호출된다는 보장은 없다. 콜 스택이 비어야 호출되므로 약간의 시간차가 발생할 수 있기 때문 4-2.bar함수 호출되어…함수 실행 컨텍스트… 과정생략… 5.전역 코드 종료. 콜 스택에서 팝. 콜 스택은 드디어 비었음 6.이벤트 루프에 의해 콜 스택 감지하고 테스트 큐->콜 스택으로 foo를 푸시하고 실행해서 현재 실행 중 상태. 이후 종료. 콜 스택 팝

function foo() {
  console.log('foo');
}

function bar() {
  console.log('bar');
}

setTimeout(foo, 0); // 0초(실제는 4ms) 후에 foo 함수가 호출된다.
bar();

댓글남기기