JavaScript는 단일 스레드이지만 노드의 모든 I / O 및 네이티브 API 호출은 비동기 (플랫폼 별 메커니즘 사용)이거나 별도의 스레드에서 실행됩니다. (이것은 모두 libuv를 통해 처리됩니다.)
따라서 소켓에서 사용할 수있는 데이터가 있거나 기본 API 함수가 반환되면 방금 발생한 특정 이벤트에 관심이있는 JavaScript 함수를 호출하는 동기화 된 방법이 필요합니다.
경합 조건, 비 원자 메모리 액세스 등과 같은 일반 다중 스레드 응용 프로그램에서 발생하는 것과 동일한 이유로 네이티브 이벤트가 발생한 스레드에서 JS 함수를 호출하는 것은 안전하지 않습니다.
그래서 우리가하는 일은 스레드로부터 안전한 방식으로 이벤트를 큐에 배치하는 것입니다. 지나치게 단순화 된 의사 코드에서 다음과 같습니다.
lock (queue) {
queue.push(event);
}
그런 다음 메인 자바 스크립트 스레드로 돌아가서 (하지만 C 쪽에서는) 다음과 같이합니다.
while (true) {
lock (queue) {
var tickEvents = copy(queue);
queue.empty();
}
for (var i = 0; i < tickEvents.length; i++) {
InvokeJSFunction(tickEvents[i]);
}
}
은 while (true)
(실제로 노드의 소스 코드에 존재하지 않는,이 순전히 예시)을 나타내는 이벤트 루프 . 내부 for
는 큐에 있던 각 이벤트에 대해 JS 함수를 호출합니다.
이것은 틱입니다. 외부 이벤트와 관련된 0 개 이상의 콜백 함수를 동 기적으로 호출하는 것입니다. 큐가 비워지고 마지막 함수가 반환되면 틱이 끝납니다. 처음 (다음 틱)으로 돌아가서 JavaScript가 실행되는 동안 다른 스레드에서 큐에 추가 된 이벤트를 확인합니다 .
무엇을 대기열에 추가 할 수 있습니까?
process.nextTick
setTimeout
/setInterval
- I / O (에서 재료
fs
, net
등)
crypto
암호화 스트림, pbkdf2 및 PRNG와 같은 프로세서 집약적 인 기능 (실제로는 ...)
- libuv 작업 대기열 을 사용하여 동기식 C / C ++ 라이브러리 호출을 비동기식으로 만드는 모든 기본 모듈