是這樣的,今天群里基友發了張截圖
研究一下
1.頁面渲染過程
這個標題下的內容很適合做這篇文章的導讀
下面這張圖是webkit渲染過程
雖然是渲染過程,但能了解到圖片資源的加載是瀏覽器通過圖片加載器異步請求獲取的。
2.代碼執行情況
javascript是單線程序解釋器,一定時間內只能執行一段代碼。
- 同步執行的任務放到主線程按加入順序執行
- 異步任務扔到任務隊列,主線程執行完之后會從任務隊列里按照先入先出的方式取任務(忽略些細節)
setTimeout和setInterval創建的都是異步任務,扔到任務隊列,接受的第二個參數意思是再過多久取消等待狀態。里面的定時/間歇回調執行的條件是
1?? 主線程任務執行完畢
2?? 任務隊列里輪到你了:你前面沒別人了 或者 你前面有人但是他條件不足 仍處于等待執行狀態
3?? 你的等待狀態為 可以執行 了
有上述3個執行條件加上一些瀏覽器默認設置,比如最小設置時間數,立即執行的毫秒數不是0等限制和實現的不同,嚴格執行是個夢。
尤其是setInterval容易發生后一個調用在前一個調用結束前啟動。
so 先改成標準的間歇使用方式。
var img = new Image();
var timesize = 20;
img.onload = function(){//事件注冊程序扔到任務隊列-DOM0級事件注冊方法
console.log("事件上鉤了!圖片已load:"+img.height)
}
function fixTimer () {
if(!!!img.height){
console.log("沒買著繼續排隊")
setTimeout(fixTimer,timesize);//扔到任務隊列
}else{
console.log("買到啦回家!:"+img.height)
console.log("定時器 done")
}
}
img.src = "http://7jpswm.com1.z0.glb.clouddn.com/transitionSnip20160122_155.png"http://ImageLoader-瀏覽器資源異步加載
setTimeout(fixTimer,timesize);//扔到任務隊列
預測執行結果
讀過紅寶書的一定看到過這段話:
新圖像元素不一定從添加到文檔后才開始下載,只要設置了src屬性就會開始下載
為什么?
因為src一旦設置,瀏覽器就把活搶走了,開始調用ImageLoader來加載圖片,而且是瀏覽器行為
如代碼所示
任務隊列第一個是事件處理程序onload
任務隊列第二個是定時任務setTimeout
當主線程沒任務時 有三條時間線
1?? javascript 主線程輪詢任務隊列過程:有沒有可執行的 取決于 等待狀態 解鎖條件
2?? ImageLoader 資源請求過程:時間取決于圖片大小 網絡狀況
3?? 圖片資源下載完成的時間:決定解鎖 事件處理程序的執行
第一種情況
- 主線程執行完
- 圖片有點大 網還有點慢 還沒請求到
- 事件處理程序 準備好了嗎?no
- setTimeout 到時間了嗎? yes 執行 獲取到圖片高度了嗎 no 繼續創建一個扔到隊列
- 圖片請求到了 也下載完了
- 事件處理程序 準備好了嗎? yes 執行
- setTimetout 到時間了嗎?yes 執行 獲取到圖片高度了嗎 yes done
這種情況輸出為
沒買著繼續排隊
事件上鉤了!圖片已load
買到啦回家!
第二種情況
- 主線程執行完
- 圖片小 網絡快 一下就請求到 下載完了
- 事件處理程序 準備好了嗎? yes 執行
- setTimetout 到時間了嗎?yes 執行 獲取到圖片高度了嗎 yes done
這種情況輸出為
事件上鉤了!圖片已load
買到啦回家!
實際代碼跑例
第三種情況
- 主線程執行完
- 圖片大 還沒請求到
- 事件處理程序 準備好了嗎? no 不執行
- setTimetout 到時間了嗎?yes 執行 獲取到圖片高度了嗎 no 繼續排著
- 圖片大 還沒請求到
- 事件處理程序 準備好了嗎? no 不執行
- 圖片大 但是嘎嘣就請求到了
- setTimetout 到時間了嗎?yes 執行 獲取到圖片高度了嗎 yes 不用排了
- 事件處理程序 準備好了嗎? yes 執行
輸出為
沒買著繼續排隊
買到啦回家!
事件上鉤了!圖片已load
實際代碼跑例 換了個大圖
這里面你還可以加入 圖片大 請求到了 但是還沒下載到的情況分析 請看下圖
只有content download才會觸發通知事件
總結
其實還有幾種情況 比如主線程存在阻塞、定時任務中存在同步阻塞等
不過 本篇想說明的是
由于代碼運行環境的特殊性 忽略基本實現和協作實現 會造成遺漏或者不可預測的運行結果
比如這里
基本實現——瀏覽器內js的運行機制
協作實現——就是瀏覽器的資源加載器
補充
- 2016-11-14
圖片下載時在沒有禁用緩存或者沒有加請求隨機變量的情況下 會緩存。
當圖片被緩存時是無法觸發onload的。
這時候可以用img.complete來做圖片準備好觸發回調的邏輯。