博客 / 詳情

返回

再次理解異步setTimeout 方法

先看一段代碼:

console.log('-',new Date().getTime())
    for(let i = 0;i<100;i++){
        setTimeout(function(){
          console.log('exeute');
          },100);
    }
    console.log('i',new Date().getTime())

執行結果:

- 1610778978900
i 1610778978901
100 exeute

看第一個log跟第二個log時間只相差了1ms,時間短到幾乎間隔為0.

再看一段代碼:

console.log('-',new Date().getTime())
    for(let i = 0;i<100000;i++){
        setTimeout(function(){
          console.log('exeute');
          },100);
    }
    console.log('i',new Date().getTime())

執行結果

- 1610779277393
i 1610779278304
4466 exeute

過一會再去看,期間程序一直在執行,電腦還差點卡死了...
- 1610779277393
i 1610779278304
13188 exeute
不出意外的情況下,你會最終看見打印結果逐漸增加到10萬。

規律感覺如下:
一開始很快的增長到上千上萬(幾乎是同時進行的)
然後逐步遞增到10萬。

第二段代碼log時間相差了911ms。
從eventLoop異步原理,先進先出,後進後出邏輯來看確實結果如我們所願。但為何在第一段代碼裏,我們會同時看見打印了100次exeute呢?

log和時間time的曲線似乎呈現如下:
image
在前面很短相同的時間裏,同時打印excute,隨後time逐漸增加。
其實在A這個區塊內,也是滿足先進先出後進後出的邏輯的,一段近乎水平
的增長曲線(可以理解成前半部分,比如i取100個的時候,“幾乎”是同時log,這裏無窮小的時間可以理解成0,所以在A這個區域,我們肉眼看見的先進先出沒觀察到

這裏用到setTimeout的知識點:
1、待加入隊列的消息和一個時間值(可選,默認為 0)。這個時間值代表了消息被實際加入到隊列的最小延遲時間。如果隊列中沒有其它消息並且棧為空,在這段延遲時間過去之後,消息會被馬上處理(能看肉眼看到的一致)。但是,如果有其它消息,setTimeout 消息必須等待其它消息處理完(所以為何10萬級for循環log的時候,我們會源源不斷的看見被打印)。因此第二個參數僅僅表示最少延遲時間,而非確切的等待時間

user avatar tigerandflower 頭像 esunr 頭像 coderleo 頭像 jianqiangdepaobuxie 頭像 201926 頭像
5 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.