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가 종료됨.
- MainContext →
- three() →
- two() →
- one() →
- one() 이 종료되며
Call Stack
에서 제거됨. →
- two()에서 호출한 one() 이 반환되고 그 결과값으로 one() + 1이 반환되며 제거됨. →
- three()에서 호출한 two() 이 반환되고 그 결과값으로 two() + 1이 반환되며 제거됨. →
- 결과값 3을 보여주고 →
- 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);
});
- MainContext →
- asyncAdd() →
- setTimeout() →
- setTimeout() 안에 있는 , cb() →
Web APIs
영역으로 setTimeout(), cb() 를 옮김 →
- asyncAdd() 함수 제거 →
- setTimeout() 에서 3초가 경과하면 setTimeout() 는 제거되고, cb() 함수는
Callback Queue
영역으로 이동 →
Event Loop
가Callback Queue
에서 cb()를Call Stack
으로 이동. →
- cb() 수행 후 제거 →
- MainContext 제거(프로그램 종료)