JavaScript———從setTimeout與setInterval到AJAX異步

setTimeout與setInterval執行

  首先咱們看一下如下代碼打印結果javascript

  console.log(1);

  setTimeout(function() { console.log(2); },100)

  setTimeout(function() { console.log(3); },50)

  console.log(4); 

  打印結果是 一、四、三、2,你可能以爲理所應當,那咱們再看下下面這個例子java

  console.log(1);

  setTimeout(function() { console.log(2); },0)

  console.log(3); 

 

  此次的結果又會是什麼呢?瀏覽器

  一、三、2,不是一、二、3。到這裏你可能會有疑惑了,明明定時器設置的時間爲0,並且瀏覽器解析js是按照從上到下執行的,應該是一、二、3纔對啊?異步

  到這裏咱們要提一下瀏覽器的線程問題。函數

  與js相關的瀏覽器線程有三個(注意:js解析是單線程) - js代碼執行線程( 主線程 ) - UI渲染線程 - 事件循環線程spa

  其中js代碼執行線程與UI渲染線程二者是互斥的,也就是說js代碼執行線程運行的時候,UI渲染線程會中止工做,這樣作也是爲了防止js中的DOM操做會致使兩線程衝突;而事件循環線程比較特殊,接下來會根據setTimerout的執行過程進行講解其做用。線程

  回到上面的第一道題目code

  console.log(1);

  setTimeout(function() { console.log(2); },100)

  setTimeout(function() { console.log(3); },50)

  console.log(4); 

  執行過程:blog

  1. js主線程運行,遇到console.log(1),直接運行,在控制檯輸出結果;隊列

  2. 主線程繼續運行,而後遇到第一個setTimeout,接着setTimeout中的回調函數會被放入到一個事件隊列中(這裏的事件隊裏能夠想象成一個備忘錄,裏面記錄的全是一些須要作而未作的事);

  3. 遇到第二個setTimeout,其中的回調函數依然被加入到事件隊列中;

  4. 執行console.log(4),到這裏主線程的任務所有執行完畢,除了setTimeout裏面的回調函數;

  5. 這個時候,咱們還未說明的事件循環線程開始工做,它會去循環遍歷事件隊列(也就是咱們的備忘錄),若是事件隊列中有回調函數,它就會將事件隊列中的回調函數從新交給主線程;

  6. 主線程收到回調函數,而後開始執行函數體。(這裏要注意,由於兩個setTimeout自己有執行時間,因此在這裏的時候就會根據時間的長短按順序執行啦。)

  setInterval原理與之相同,不做另說。

 

  總的來講,setTimeout與setInterval的執行會等到主線程的全部任務所有執行後,纔會再執行其中的回調函數,因此在使用它們的時候也要注意,特別是在主線程中有特別耗時的任務的時候,兩種定時器會被不可預測的延後。

  講到這裏,你們有沒有想到什麼呢?

  恩,就是異步,setTimeout的執行有沒有一點異步的感受呢?但又由於它必須是等到主線程所有執行完纔會執行,因此能夠稱之爲僞異步。

  說到異步,咱們還會想到AJAX,都說AJAX是異步,可是它異步的原理想必還不清楚的你應該有點興趣瞭解的。

  異步:簡單說就是在處理某一件事的時候還能夠去作別的事,好比:你在銀行取號後等待取錢,在等待的過程當中你還能夠玩手機,和別人聊天等等,這個過程就是異步的。

AJAX 異步的原理

  1. 發送一個AJAX請求的時候,瀏覽器會有一個專門的線程來進行該任務;
  2. 而在AJAX中也是有回調函數的,好比請求成功後的回調,失敗後的回調,這些回調函數與setTimeout中的回調同樣會被推入到事件隊列中;
  3. 瀏覽器接會再次提供一個縣城接收AJAX請求返回的數據;
  4. 事件循環線程這時候知道事件隊列中AJAX的回調函數可以被執行了,遍歷事件隊列,將其中的回調函數交回給js主線程;
  5. 主線程執行AJAX回調函數內部代碼。

  總的說來,AJAX的請求不會干擾到主線程任務的執行,它有本身專供的線程來處理其任務,就像是瀏覽器的親兒子~~~

相關文章
相關標籤/搜索