由script標籤引起了我對setTimeout異步的思考

咱們都知道在JS中setTimeout是異步執行機制的

像setTimeout(function(){},0)這樣

若是在這條語句後面還有不少的同步任務,
它必需要等這些同步任務完成纔會執行setTimeout裏面的內容javascript

setTimeout(function(){
    很差意思,我要等for循環的同步任務完成才能執行
},0)
for(var i = 0; i < 99999999999; i++){
    這裏的任務完成了,纔會執行setTimeout的內容
}

那麼我所發現的這個問題以下:
如代碼所示:在body中插入兩個script標籤
<body>java

<script>
    alert('fir-script');
    setTimeout(()=>{
        alert('setTime');
    },0);
</script>
<script>
    alert('sec-script');
    var str = '測試的字符串';
    alert(str);
</script>

</body>異步

這裏所用的測試字符串是中文
這裏須要作3個實驗,分爲A、B、C測試

實驗A:用比較短的字符串,(有5箇中文字體)來測試,執行的彈窗結果是:
fir-script -> sec-script -> '測試字符串' -> setTime

實驗B:用較長的字符串,(有45000箇中文字體)來測試,結果發現了變化 執行的彈窗結果是:
fir-script ->setTime -> sec-script -> '測試字符串'

實驗C:減小部分字符串,(有43000箇中文字體)來測試,執行的彈窗結果是:
fir-script -> sec-script -> '測試字符串' -> setTime

在其餘條件沒有變化的狀況下(注意:三次測試setTiemout的時間都是0)
程序執行的順序彷佛和字符串的長度有關
(那其實能夠說是和script裏面的內容大小有關,那也能夠進一步理解爲和解析script內容的時間有關)字體

爲了驗證上述結論(執行順序和解析script內容的時間有關)
在實驗B的基礎上,對setTiemout的時間進行更改,其餘保持不變
如B(5)爲5ms後執行,即setTimeout(()=>{alert('setTime');},5);
下面咱們看一下結果:線程

B(0): fir-script -> setTime -> sec-script -> '測試字符串'
B(5): fir-script -> setTime -> sec-script -> '測試字符串'
B(10): fir-script ->sec-script -> '測試字符串' -> setTime
B(15): fir-script -> sec-script ->'測試字符串' -> setTime

從上面幾個實驗咱們能夠在側面看出一個現象
setTime 不會出如今 sec-script 和 '測試字符串' 之間
這也反映了JS是單線程執行的,並且在同步任務裏,不受其餘script標籤的影響code

經過這個案例,發現了一些問題,總結以下:ip

若有其餘外部腳本(即便這些腳本都是同步任務),像setTiemout這些異步任務,不會等待全部同步任務執行完成
只有在同一個script標籤裏,異步任務要等待該標籤的全部同步任務完成纔會執行
由於須要去解析腳本,而解析腳本與執行另外的腳本不衝突

最後的最後,若是你在嘗試過程當中發現與本文的結果不相同,請把測試用的案例」增強「,如把字符串加到10W,這是由於setTimeout的不肯定性
歡迎你們一塊兒來探討字符串

相關文章
相關標籤/搜索