JavaScript, 싱글 스레드 기반 언어 : 한번에 하나씩 작업 수행, 이벤트 루프를 이용해 비동기 방식으로 동시성 지원한다.
이벤트 루프란 ?
: Callback Event Queue에서 하나씩 꺼내서 동작시키는 Loop을 말한다. 위의 그림 전체를 말하는 것 같다.
태스크 큐 ?
: web api에서 비동기 작업들이 실행된 후 호출되는 콜백함수들이 기다리는 공간, FIFO, 하나의 큐로 이루어있지 않고 Microtask Queue, Animation Frames 등 여러개의 큐로 이루어져 있다.
Web API ?
: 브라우저에서 자체 지원하는 api이다. DOM이벤트, AJAX, setTimeout 등의 비동기 작업 등을 수행할 수 있도록 api를 지원한다.
이벤트 루프 프로세스
- 코드가 호출스택에 쌓이고 실행되면 자바스크립트 엔진은 비동기 작업을 Web API에게 위임
- Web API 는 해당 비동기 작업을 수행, 콜백 함수를 이벤트 루프를 통해 태스크 큐에 전달
- 이벤트 루프는 콜 스택에 쌓여있는 함수가 없을 때, 태스크 큐에서 대기하고 있던 콜백함수를 콜 스택으로 넘겨준다.
- 콜 스택에 쌓인 콜백함수가 실행되고 실행된 함수는 제거된다.
실습
자바스크립트의 이벤트 루프(event loop)가 어떻게 tasks와 microtasks를 처리하는지에 대해 알아보좌
Task 에 들어가는 것과 microTask에 들어가는 것이 무엇인지 아는게 중요한 것 같다.
console.log가 어떻게 찍힐지 맞춰보기 !
예제 1.
console.log('script start');
setTimeout(() => {
console.log('setTimeout ');
}, 0);
Promise.resolve()
.then(() => {
console.log('promise1');
})
.then(() => {
console.log('promise2');
})
console.log('script end');
정답
script start
script end
promise1
promise2
setTimeout
*하지만 Microsoft Edge, Firefox 40, ios safari, desktop safari 8.0.8에서는 setTimeout이 promise보다 먼저 찍힌다고 한다.
실행 순서
Script -> Tasks -> Microtasks
setTimeout는 Tasks로 promise는 micotasks로 분류된다.
예제 2
// Let's get hold of those elements
var outer = document.querySelector('.outer');
var inner = document.querySelector('.inner');
// Let's listen for attribute changes on the
// outer element
new MutationObserver(function () {
console.log('mutate');
}).observe(outer, {
attributes: true,
});
// Here's a click listener…
function onClick() {
console.log('click');
setTimeout(function () {
console.log('timeout');
}, 0);
Promise.resolve().then(function () {
console.log('promise');
});
outer.setAttribute('data-random', Math.random());
}
// …which we'll attach to both elements
inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);
inner의 'click'이벤트 실행됨 -> onClickd 함수 실행 -> "click" 콘솔 찍힘 -> setTimeout - Task에 담아짐 -> Promise - microTasks에 담아짐 -> outer.setAttribute 실행 -> new MutationObserver - microTasks에 담아짐 -> microTasks에 담긴 promise, new mutationObserver 순차적 실행 -> "promise", "mutate" 콘솔 찍힘 -> microTasks 비워지면 바로 Tasks실행이 아니라 script 아래 outer 'click'이벤트 실행 -> onClick 함수 실행 -> "click" 콘솔 찍힘 -> setTimeout - Task에 담아짐 -> promise - microTasks에 담아짐 -> new MutationObserver - microTasks에 담아짐 -> microTasks 순차 실행 -> "promise" 콘솔 찍힘 -> "mutate" 콘솔 찍힘 -> Tasks에 담겨져 있던 setTimeout 두 개 실행 -> "timeout" 콘솔 찍힘 -> "timeout" 콘솔 찍힘 -> 끝
찍히는 콘솔 로그
click
promise
mutate
click
promise
mutate
timeout
timeout
Reference : https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
https://www.youtube.com/watch?v=8aGhZQkoFbQ&ab_channel=JSConf
https://www.youtube.com/watch?v=wcxWlyps4Vg&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9CTech
https://www.youtube.com/watch?v=cCOL7MC4Pl0&ab_channel=JSConf
https://zereight.tistory.com/855
'Javascript' 카테고리의 다른 글
[Javascript] 날짜 더하고 빼기 / How to set or add months, days, hours to Date / moment 라이브러리 (0) | 2022.06.24 |
---|---|
[JavaScript] Convert a Unix timestamp to time / 유닉스 시간으로 변환하기 (0) | 2022.06.24 |
[JavaScript] 콘솔로그 전체 보기 / console.log more items.. 전체 펼쳐보기 (0) | 2022.04.21 |
[JavaScript] 객체 복사하기 <옅은 복사 vs 깊은 복사> (0) | 2022.02.19 |
[JavaScript] 핸드폰번호, 생년월일 - 하이픈 자동 삽입하기 / Backspace keyCode (0) | 2021.06.28 |