자바스크립트와 이벤트 큐!

그래서 우리 모두는 JavaScript의 정의를 알고 있습니다. JavaScript는 단일 스레드 동기식 언어입니다.
즉, 하나의 호출 스택과 하나의 메모리 힙이 있고 코드를 순서대로 실행하고 다음으로 이동하기 전에 코드 조각 실행을 완료해야 하므로 언어가 본질적으로 차단됩니다.

다시 JavaScript는 동기식이며 단일 스레드이므로 페이지에서 JavaScript 코드 블록을 실행하면 동일한 페이지에서 다른 JavaScript 코드가 병렬로 실행되지 않습니다!

우리 모두 JS를 사용하여 비동기식 항목을 사용하기 때문에 정의가 터무니없는 것 같습니다. 아니면 모두 환상입니까?

따라서 이 주제에 대해 읽은 다양한 리소스에서 내가 이해한 내용은 다음과 같습니다.

자바스크립트 자체는 동기식이지만 브라우저는 비동기식으로 코딩이 가능합니다. 어떤가요?

답은 다음과 같습니다.

by using the Browser APIs, such as Fetch API, setTimeout, Promises, Geolocation API etc ..



비동기 함수가 호출될 때마다 브라우저 API로 전송되며 이는 브라우저에 내장된 API입니다.
호출 스택에서 받은 명령에 따라 API는 자체 단일 스레드 작업을 시작합니다.

이에 대한 예는 setTimeout 메소드입니다.
호출 스택에서 setTimeout 작업이 처리되면 이 작업을 다시 처리하기 위해 지정된 시간까지 대기하는 해당 API로 전송됩니다.
작업을 어디로 보내나요? 이벤트 큐.

이벤트 루프는 호출 스택이 비어 있는지 여부를 지속적으로 확인하고, 비어 있으면 이벤트 큐에서 새 함수를 추가하고, 그렇지 않으면 현재 함수 호출을 처리합니다.

따라서 이벤트 큐 자체에 대해 자세히 살펴보겠습니다.
이 모든 것을 이해하려면 먼저 몇 가지 용어에 대해 이야기해야 합니다.

  • Tasks : any block of code (literally)
  • Browser APIs : APIs that usually start their own threads to run code parallelly ( most of them requires a callback which will later on be pushed to the event queue )
  • Micro Tasks : any callback related to a promise
  • rendering process : anything related to rendering such as style calculation, or any requestAnimationFrame callback
  • call stack : a mechanism for an interpreter to keep track of its place in a script that calls multiple functions ( what function is currently being run and what function initially called it ).
  • Heap : an area of pre-reserved computer main storage ( memory ) that a program process can use to store data
  • Thread : a sequence of programmed instructions that can be managed independently by a scheduler it got its own heap and stack.


모든 것을 이해할 시간입니다!
그래서 우리는 기본 스레드가 자바스크립트를 동기적으로 실행한다고 말했습니다. 스택에서 해당 명령이 실행될 때 특정 BrowserAPI를 사용할 때 코드를 독립적으로 실행하는 새 스레드가 시작됩니다.



예를 들어 setTimeout을 살펴보겠습니다. 새 스레드는 X ms가 실행될 때까지 sysTick을 계속 추적합니다. 새 스레드는 기본 스레드에 연결된 콜백을 이벤트 큐에 넣도록(푸시) 메시지를 보내고, 이벤트 루프는 그런 다음 호출 스택이 비워질 때까지 대기하여 일부 콜백을 스택에 넣은 다음 실행합니다.

체계는 그것을 완벽하게 설명합니다.
주목해야 할 중요한 점은 모든 콜백이 동일한 우선 순위와 동일한 실행 또는 인큐 순서를 가지지 않는다는 것입니다.
JSconf 프레젠테이션에서 본 재미있는 표현은 이벤트 루프를 다음과 같이 설명합니다.


while(true){
   var Queue = getNextQueue();
   var Task = queue.pop();
   Execute(task);

   while(microtaskQueue.hasTasks){
      doMicrotask();
   }

   if(isRepaintTime()){
      animationTasks = animationQueue.copyTasks();
      for ( task in animationTasks)
         doAnimationTask(task);
      repaint();
   }
}


많은 출처에서 설명하듯이 MicroTasks는 일반적으로 콜백을 약속합니다. 이벤트 큐로 푸시할 때 전체 MicroTask 큐를 푸시하는 반면 태스크를 푸시할 때는 작업 큐에서 선입 콜백만 푸시합니다.

또한 렌더링할 시간이 되면 전체 렌더링 대기열을 이벤트 대기열로 푸시합니다(대부분의 브라우저는 60Hz의 빈도로 실행되기 때문에 일반적으로 브라우저는 16/17ms마다 화면을 다시 그립니다).
따라서 간단한 작업이나 미세 작업에서 애니메이션을 실행하는 것보다 requestAnimationFrame을 사용하여 애니메이션을 실행하는 것이 좋습니다. 더 높은 빈도로 애니메이션을 다시 그리는 것은 의미가 없기 때문에 인간의 눈은 초당 30~60프레임(30/60Hz)을 볼 수 있습니다.

JSConf의 또 다른 프레젠테이션은 다음과 같이 이벤트 루프를 시각화합니다.



그래서 결론으로:

The event loop is the secret behind JavaScript's asynchronous programming. JavaScript executes all operations on a single thread, but using a few smart data structures, it gives us the illusion of multi-threading, so describing JavaScript as asynchronous is arguably misleading.



어쨌든 이것이 의미가 있기를 바랍니다. 그렇지 않다면 이 프레젠테이션을 확인하여 시청하는 것이 좋습니다. 훨씬 더 잘 이해하게 될 것입니다.



의견 섹션에서 자유롭게 설명하거나 주제에 대한 추가 링크를 제공하십시오.
읽어 주셔서 감사합니다.

좋은 웹페이지 즐겨찾기