前端監聽資源載入錯誤
前言
頁面上有很多資源元素,比如<img>
,<iframe>
等,我們需要知道其載入情況,根據載入成功與否進行下一步的處理。
常見的做法是給這些元素上設定onload
,onerror
方法。
比如:<img onerror="errFn()" onload="loadFn()">
支援onload
的標籤:<body>, <frame>, <frameset>, <iframe>, <img>, <input type="image">, <link>, <script>, <style>
支援onerror
的標籤:<img>, <input type="image">, <object>, <script>, <style> , <audio>, <video>
注意IE9.0及以上才支援<audio>, <video>
標籤
此外幾乎所有瀏覽器都支援onload
和onerror
,
這種做法的缺點:
<audio>, <video>
參考ofollow,noindex" target="_blank">JS錯誤監控總結
一文,我們採用window.addEventListener("error",()=>{})
的方法
window.addEventListener
window.addEventListener('error')
與window.onerror的異同點在於:
- 前者能夠捕獲到資源載入錯誤,後者不能。
- 都能捕獲js執行時錯誤,捕獲到的錯誤引數不同。前者引數為一個event物件;後者為 msg, url, lineNo, columnNo, error一系列引數。event物件中都含有後者引數的資訊。
用法如下:
window.addEventListener('error', function (event) { console.log(event) if (event) { var target = event.target || event.srcElement; // 寫上 var isElementTarget = target instanceof HTMLElement if (!isElementTarget) return; // js error不再處理 var source = event.path[0] // 對該資源進行處理.. } //設為true表示捕獲階段呼叫,會在元素的onerror前呼叫 }, true)
上面說過,<iframe>
支援 onload 不支援 onerror,故以上程式碼不會監聽到iframe載入失敗事件
此外,由於window.addEventListener('load')
是監聽文件是否載入完畢,故無法監聽資源載入成功事件
最終方案: document.addEventListener
document.addEventListener
可以用來監聽Element元素
的載入情況
對於iframe來說,我們只能監聽load,至於判斷是否載入成功,我們可以通過:event.path[0].contentWindow!==null
來判斷。
只要請求響應成功,該 contentWindow 就不會為null。
注意:對於設定了X-Frame-Options:DENY
響應的情況,由於請求響應是ok的,所以 contentWindow 不會為空。
這種情況是否屬於資源載入錯誤屬於產品層面定義。
若歸類為載入錯誤,暫未找到完美的解決方案。
同域的話可以訪問 contetnDocument, 看裡面內容是否為空(僅只有head和body標籤)
完整程式碼如下:
document.addEventListener('load', function (event) { if (event) { var target = event.path[0] if(target.localName==='iframe'&&!target.contentWindow){ //資源載入錯誤處理.. } else{ //資源載入成功處理.. } } }, true) document.addEventListener('error', function (event) { if (event) { var target = event.path[0] // 資源載入錯誤處理.. target.outerHTML 拿到原標籤內容,例 <img src="./img/a.png"> } //設為true表示捕獲階段呼叫,會在元素的onerror前呼叫,在window.addEventListener('error')後呼叫 }, true)