Home >Web Front-end >JS Tutorial >Understanding single thread in javascript timer_javascript skills

Understanding single thread in javascript timer_javascript skills

WBOY
WBOYOriginal
2016-05-16 15:14:177801browse

1. The JavaScript engine is single-threaded

As you can see from the code below, the first code using setTimeout is an infinite loop. Since it is a single thread, the following two timers have no chance to execute.

<script type="text/javascript">
 setTimeout( function(){ while(true){} } , 100); 
 setTimeout( function(){ alert('你好!setTimeout'); } , 200); 
 setInterval( function(){ alert('你好!setInterval'); } , 200); 
</script>

The kernel of the browser is multi-threaded. They cooperate with each other under the control of the kernel to maintain synchronization. A browser implements at least 3 resident threads: javascript engine thread, GUI rendering thread, and browser event triggering thread.

The JavaScript engine is based on event-driven single-thread execution. The JS engine has been waiting for the arrival of tasks in the task queue and then processed them. The browser has only one JS thread running the JS program at any time.
The GUI rendering thread is responsible for rendering the browser interface. This thread will be executed when the interface needs to be repainted (Repaint) or when a reflow (reflow) is caused by a certain operation. However, it should be noted that the GUI rendering thread and the JS engine are mutually exclusive. The GUI thread will be suspended when the JS engine is executed, and the GUI updates will be saved in a queue and will be executed immediately when the JS engine is idle.
The browser event trigger thread. When an event is triggered, the thread will add the event to the end of the pending queue and wait for processing by the JS engine. These events can come from the code block currently executed by the JavaScript engine such as setTimeOut, or from other threads in the browser kernel such as mouse clicks, AJAX asynchronous requests, etc. However, due to the single-threaded relationship of JS, all these events have to be queued for processing by the JS engine.

As can be seen from the picture above, the JavaScript engine in the browser is event-driven. The events here can be regarded as various tasks assigned to it by the browser. The JavaScript engine has been waiting for the arrival of tasks in the task queue. , due to the single-threaded relationship, these tasks have to be queued and processed by the engine one after another.

t1, t2....tn represents different time points, and the corresponding small squares below tn represent the tasks at that time point.

t1 time:

1. GUI rendering thread
2. Browser event trigger thread:

During the t1 time period, the user first clicks a mouse button. The click is captured by the browser event trigger thread and forms a mouse click event. As can be seen from the figure, for the JavaScript engine thread, this event is asynchronously transmitted from other threads. At the end of the task queue, because the engine is processing the task at t1, this mouse click event is waiting to be processed.
3. Timing trigger thread:
The browser model timing counter here is not counted by the JavaScript engine, because the JavaScript engine is single-threaded. If it is in a blocked thread state, it cannot count the time. It must rely on the outside to time and trigger timing, so the timing event in the queue is Asynchronous events.
4. During this time period of t1, after the mouse click event is triggered, the previously set setTimeout timing also arrives. At this time, for the JavaScript engine, the timing trigger thread generates an asynchronous timing event and puts it in the task queue. This event is queued after the click event callback, waiting to be processed. In the same way, still within the t1 period, a setInterval timer is also added next. Because it is an interval timer, it is triggered twice in a row within the t1 period. These two events are queued to the end of the queue to be processed.
5. Ajax asynchronous request:
The browser opens a new http thread request. When the status of the request changes, if a callback has been set previously, the asynchronous thread will generate a status change event and put it in the JavaScript engine's processing queue to wait for processing.
2. The execution order of tasks is different, and the display results are also different

1) The setTimeout function is not used

A code example found on the Internet is used here to demonstrate.

<a href="#" id="doBtn">do something</a>
<div id="status"></div>
<script type="text/javascript">
  var doBtn = document.getElementById('doBtn')
   , status = document.getElementById('status');

  function sleep(ms) {
  var start = new Date();
  while (new Date() - start <= ms) {}
  }
  
  doBtn.onclick = function(e) {
   status.innerHTML = 'doing...please wait...'; 
   sleep(3000); // 模拟一个耗时较长的计算过程,3s
   status.innerHTML = 'done'; 
   return false;
  };
</script>

I executed the above code in firefox. The plan is to click the "do something" button, then display "doing...please wait...", then execute sleep, and finally display "done".

But the result is that after clicking, the browser gets stuck for about 3 seconds, and finally displays done directly.

From the analysis, it can be seen that when setting status.innerHTML, the GUI rendering thread needs to be executed, but the JavaScript engine thread is still executed, and the JavaScript engine thread and the GUI rendering thread are mutually exclusive, so in the end done is shown.

2) Use the setTimeout function

<a href="#" id="doBtn2">do something timer</a>
<div id="status2"></div>
<script type="text/javascript">
  var doBtn2 = document.getElementById('doBtn2')
   , status2 = document.getElementById('status2');

  function sleep2(ms) {
  var start = new Date();
  while (new Date() - start <= ms) {}
  }
  
  doBtn2.onclick = function(e) {
   status2.innerHTML = 'doing...please wait...'; 
   setTimeout(function() {
   sleep2(3000); 
   status2.innerHTML = 'done'; 
   }, 100); 
   return false;
  };
</script>

Add a setTimeout after "doing...please wait..." to delay execution and give the browser time to render. At this time, "doing...please wait..." will be displayed. words, then execute the sleep function, and finally display "done".

Later some netizens found that it did not work in Firefox. This problem did exist. Later I modified the code and put the declaration of local variables and the binding of onclick into the window.onload event. After the page structure is loaded, , I will do the script operation again.

<script type="text/javascript">
  function sleep(ms) {
  //...
  }
  window.onload = function() {
   var doBtn = document.getElementById('doBtn'),
   status = document.getElementById('status');
   
   var doBtn2 = document.getElementById('doBtn2')
    , status2 = document.getElementById('status2');
    
   doBtn.onclick = function(e) {
    //...
   };
   doBtn2.onclick = function(e) {
    //...
   };
  };
</script>

The above is the entire content of this article, I hope it will be helpful to everyone’s study.

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn