매일 한줄 코딩

12. javascript 동기 / 비동기 본문

develop/javascript

12. javascript 동기 / 비동기

ShipJH 2022. 9. 11. 22:01
3. 동기 / 비동기

3. 동기 / 비동기

동기와 비동기 코드

자바스크립크는 싱글스레드로 동작한다. (동기 혹은 블로킹방식)

동기적 작업을 극복하기위해 비동기(논블로킹방식)방식을 사용한다.

1. 동기

function taskA() {
  console.log("A 작업 끝");
}

taskA();
console.log("끝"); //taskA() 가 끝나야 실행.

/*
A 작업 끝
끝
*/

2. 비동기

function taskA() {
  setTimeout(() => {
    console.log("A 작업 끝");
  }, 2000); // 콜백함수를 이용하여 2초뒤
} 

taskA();
console.log("끝"); 


/*
끝
A 작업 끝
*/

2-1. 비동기 콜백지정

변수 2개를 받아 더해준 결과를 밖에서 이용하고자 한다면 콜백함수를 이용한다.

function taskA(a, b, cb) { // 콜백함수 추가.
  setTimeout(() => {
    const response = a + b; // const response 는 지역변수로 밖에서 쓸수 없기 때문에..
    cb(response); // cb라는 콜백함수에 넣어주었다.
  }, 3000);
}

taskA(3, 4, (response) => {console.log("A 테스크 끝:", response);}); // 받을 콜백함수도 같이 파라미터에 넘겨줌.
console.log("끝");

/*
끝 
A 테스크 끝: 7
*/

여러개일때..

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

function taskB(a, cb) {
  setTimeout(() => {
    const response = a * 2;
    cb(response);
  }, 1000);
}

function taskC(a, cb) {
  setTimeout(() => {
    const response = a * -1;
    cb(response);
  }, 2000);
}

taskA(3, 4, (response) => {
  console.log("A 테스크 끝:", response);
});

taskB(10, (response) => {
  console.log("B 테스크 끝", response);
});

taskC(100, (response) => {
  console.log("C 테스크 끝", response);
});

console.log("끝");

/*
끝 
B 테스크 끝 20
C 테스크 끝 -100
A 테스크 끝: 7
*/


JS Engine

Heap : 변수나 상수들에 사용되는 메모리 할당 부분

Call Stack: 코드에 실행에따라 호출 스택을 쌓는 부분.

1. 동기방식에서 Call Stack

Call Stack 가 쌓이는 예시

// MainContext: 1

function one() { // 5 반환 후 종료되므로 제거됨.
  return 1;
}

function two() {
  return one() + 1; // 4. one호출 / 6. one() + 1을 반환후 제거됨
}

function three() {
  return two() + 1; // 3. two호출 / 7. two() + 1을 반환후 제거됨
}

console.log(three()); // 2. three 호출 // 8. 결과 값을 보여주고

//프로그램 종료 
//9. MainContext 제거 됨.

MainContext 는 프로그램이 시작될때 처음에 쌓이고, 종료되면 MainContext가 종료됨.

  1. MainContext →
  1. three() →
  1. two() →
  1. one() →
  1. one() 이 종료되며 Call Stack 에서 제거됨. →
  1. two()에서 호출한 one() 이 반환되고 그 결과값으로 one() + 1이 반환되며 제거됨. →
  1. three()에서 호출한 two() 이 반환되고 그 결과값으로 two() + 1이 반환되며 제거됨. →
  1. 결과값 3을 보여주고 →
  1. MainContext 제거(프로그램 종료)

이처럼 JS는 Call Stack 이 하나이기 때문에 동기처럼 구현된다.

2. 비동기 방식에서 Call Stack

Call Stack 쌓이는 예시


// MainContext: 1

function asyncAdd(a, b, cb) {
  setTimeout(() => { // 3
    const response = a + b;
    cb(response); // 4
  }, 3000);
}

// 5 (3),(4) 함수를 Web APIs 영역으로 이동시킴.

asyncAdd(1, 3, (res) => { // 2  / 6.제거
  console.log("결과:", res);
});
  1. MainContext →
  1. asyncAdd() →
  1. setTimeout() →
  1. setTimeout() 안에 있는 , cb() →
  1. Web APIs 영역으로 setTimeout(), cb() 를 옮김 →
  1. asyncAdd() 함수 제거 →
  1. setTimeout() 에서 3초가 경과하면 setTimeout() 는 제거되고, cb() 함수는 Callback Queue 영역으로 이동 →
  1. Event LoopCallback Queue 에서 cb()를 Call Stack 으로 이동. →
  1. cb() 수행 후 제거 →
  1. MainContext 제거(프로그램 종료)


Comments