자바스크립트는 싱글스레이드이면서 비동기처리도 가능한데, 자바스크립트 언어의 비동기 행위들은 엄밀히 말하면 자바스크립트 언어 그 자체의 일부는 아니다. 오히려 비동기 행위는 브라우저 내부(혹은 프로그래밍 환경)에 존재하는 자바스크립트 언어의 핵심단의 상위에 만들어졌다. 또한 브라우저의 API를 통해 접근한다.
이러한것들은 자바스크립트 언어 그 자체는 아니고 오히려 자바스크립트 언어 코어 단의 상위에 만들어져, 자바스크립트 코드 사용시에 추가적인 능력을 제공한다
. 예를 들면 Geolocation API 는 지역 데이터를 가져오기위한 간단한 자브스크립트 구조를 제공한다. 위치 데이터를 불러오고 코드에서 사용할 수 있도록 브라우저 환경에 이것을 반환한다. 하지만 이러한 복잡성은 다시 API에 의해 추상화됬다.function main() {
console.log('A');
setTimeout(
function display() { console.log('B'); }
, 0);
console.log('C');
}
main();
// 출력
// A
// C
// B
'A','C'를 콘솔에 로깅하는 2개의 console.log
를 가진 main함수이다. 그리고 그사이 'B'를 로깅하는 0ms
의 딜레이를 가진 setTimeout()
함수를 호출한다.
메인 함수 호출 -> 프레임으로 stack에 push
→ 브라우저 첫번째 statement(console.log('A')
)를 stack에 넣음 → 해당 프레임은 stack에서 pop
된다.→ 'A' 콜솔에 표기.
두번째 statement(콜백display()
과 함께 0ms의 딜레이를 가진 setTimeout()
) 가 콜스택으로 push → setTimeout()
함수는 제공된 콜백을 딜레이하기 위해 브라우저 API를 사용 → 타이머를 돌리기위해 콜백이 브라우저로 넘어가면 setTimeout()
을 가진 프레임은 pop
브라우저에 display()
실행을 위한 타이머가 돌아가는 도중 console.log('C')
가 콜스택에 push
(제공된 딜레이는 0ms 였기 때문에, 콜백은 브라우저가 콜백을 받자마자 메시지 큐에 바로 추가)
마지막 statement의 실행 후 main()
프레임은 콜스텍 밖으로 pop
→ 콜스택은 빈(empty)가 된다. 브라우저가 어떤 메시지를 큐에서 콜스택으로 push하기 위해서는 먼저 콜스택을 반드시 비워야 한다. setTimeout()
의 딜레이가 0초임에도 불구 하고, display()으로의 콜백이 콜스택에 존재했던 모든 프레임이 실행될 때까지 기다려야 했던 이유이다.
콜백 display()가 콜스텍에 push된후 실행 → 'C' 가 콘솔에 나타남.
- 위의 모든 과정이 자바스크립트의 이벤트 루프이다.
setTimeout(function, delayTime)
에 들어가는 delay 파라미터는 어떤 함수가 실행된 뒤의 정확한 시간 딜레이를 말하는 것이 아닌, 함수가 실행됐을 때의 어떤 지점이후의 최소 대기시간을 의미한다.
function main() {
console.log('A');
setTimeout(
function exec() { console.log('B'); }
, 0);
runWhileLoopForNSeconds(3);
console.log('C');
}
main();
function runWhileLoopForNSeconds(sec) {
let start = Date.now(), now = start;
while (now - start < (sec*1000)) {
now = Date.now();
}
}
// Output
// A
// C
// B
runWhileLoopForNSeconds()
는 함수가 호출된 시간에서 경과된 시간을 걔속 측정하여 경과된 시간이 함수의 인자로 받은 시간과 일치한지 계속해서 검증한다. while
반복문이 콜스택에서 상주하면서 브라우저 API를 사용하지 못하게 하는 blocking statement 이다. 이 함수는 실행이 끝날 때까지 뒤에 오는 모든 statements들이 실행되지 못하게 막는다.
위의 코드에서, setTimeout()은 0초의 딜레이를 가지고 shile반복문은 3초간 실행되더라도, exec()콜백은 메시지 큐에 갇혀 있다. while 반복문은 3초가 지날 때 까지 콜스택 위에서 계속 실행된다. (jsavscript의 엔진은 싱글스레이드이기때문) 3초가 지나 콜스택이 비게 되는 순간 exec()콜백은 콜스택으로 들어와서 실행된다.
setTimeout()
의 딜레이 인자는 실행이 시작되는 타이밍을 보장해주는 것이 아니다. 최소한 얼마정도는 있다가 실행되라 정도의 의미로 생각 하는 것이 좋다.
참고