js腳本加載失敗問題解決辦法
當我們在運行某一個項目時,它的某些JavaScript腳本可能加載不出來,報錯。 像現在單頁界面應用基本上都是通過js來構建,一旦加載不出,這個項目就不能運行了,那怎么辦?我們如何解決這個問題?
這里采用的方案是,重新加載JavaScript腳本。那么什么時候去重新加載js,如何重新加載js?在js腳本加載不出來時,就需要去重試加載。那我們怎么知道js有沒有加載失敗,我們可以在<script src="https://cdn.topskys.org/v0/loadjs.js"></script>標簽上添加一個監(jiān)聽加載失敗的事件 οnerrοr="console.log('error')",當出現錯誤會觸發(fā)onerror事件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script onerror="console.log('error')" src="https://cdn.topskys.org/v0/loadjs.js"></script> </body> </html>
可以看到,當加載js出現錯誤時,onerror監(jiān)聽到了錯誤。但是在工程化的環(huán)境,這些<script></script>標簽元素都是自動生成的,給這些標簽添加上onerror事件,這種方式又特別麻煩。我們可以給整個window添加error監(jiān)聽事件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script src="https://cdn.topskys.org/v0/loadjs.js"></script> <script> window.addEventListener("error",e=>{ console.log("error loading") }); </script> </body> </html>
但上一個js腳本加載出現錯誤,window監(jiān)聽error事件還有沒有注冊,所以說我們需要把它寫在最前邊,放到<head></head>里,一開始就去監(jiān)聽。當然,寫到最前邊它也不會觸發(fā),因為它不會事件冒泡,只能在捕獲階段就拿到該事件,在監(jiān)聽事件函數后加“, true”:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script> window.addEventListener("error", e => { console.log("error loading") },true); // 捕獲階段拿到事件 </script> </head> <body> <script src="https://cdn.topskys.org/v0/loadjs.js"></script> </body> </html>
觸發(fā)error的事件類型也很多,如圖片加載錯誤、在js中throw 1報錯也會觸發(fā)error。我么怎么樣縮小觸發(fā)error的范圍,只監(jiān)聽到那些<script src=""></script> 加載js不出來的情況?我們發(fā)現error事件中,參數e輸入的target是script元素:
但是呢,throw 在error事件里報的是ErrorEvent錯誤,里面包含各種屬性,故我們可以準確地找到某一種錯誤。
<script> throw 1; </script>
我們需要在window監(jiān)聽error事件里面作一個判斷:
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script> window.addEventListener("error", e => { const tag=e.target if(tag.tagName==='SCRIPT' && !(e instanceof ErrorEvent)) { console.log("JS 加載錯誤") } },true); </script> </head>
到這里頁面解決了,什么時候去重新加載js的問題,還剩下如何重試加載js。
首先,我們需要引入多個新地址的script標簽加載js,當某一個js加載失敗時,就會被觸發(fā)window監(jiān)聽事件error,執(zhí)行重試更換域名生成新的script標簽加載js,需要靠document.write()才能阻塞后面的js加載,不阻塞后續(xù)js加載,會造成js加載順序混亂。
注意,在使用document.write()寫入script標簽時,需要對標簽結束符進行轉譯,否則會被認為是上個標簽的結束符。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script> const domains = ["https://cdn.topskys.org/v0", "https://cdn.topskys1.org/v1", "https://cdn.topskys2.org/v2"]; // 重試域名數組 const maxRetry=3; // 最多重試次數 const retryInfo={}; // 記錄重試次數及下一個重試的域名數組下標{times:1,nextIndex:2} window.addEventListener("error", e => { const tag = e.target if (tag.tagName === 'SCRIPT' && !(e instanceof ErrorEvent)) { // console.log("JS 加載錯誤") const url=new URL(tag.src) // 拿到script標簽的src域名 if(!retryInfo[url.pathname]){ retryInfo[url.pathname]={ times:0, nextIndex:0, } } const info=retryInfo[url.pathname]; // 取出文件路徑 ./loadjs.js ./js.js ./y.js const script=document.createElement("script") url.host=domains[info.nextIndex]; // 更換域名 document.write(`<script src="${url.toString()}">\<\/script>`); // 新加載script元素,需要阻塞后面的script加載js,否則加載js順序會亂。注意轉譯</script>,否則會被認為上面的script結束標簽。 script.src=url.toString(); document.body.insertBefore(script,tag); // 將新的script標簽插入加載錯誤標簽前 // 修改重試信息 info.times++; info.nextIndex=(info.nextIndex+1)%domains.length; } }, true); </script> </head> <body> <script src="https://cdn.topskys.org/v0/js.js"></script> <script src="https://cdn.xx1.cn/y.js"></script> <script src="https://cdn.xx2.com/loadjs.js"></script> </body> </html>
那么,如何解決js加載失敗的問題就解決了。但如果script標簽上有defer、async及工程化項目中呢,有如何該解決?
總結
到此這篇關于js腳本加載失敗問題解決辦法的文章就介紹到這了,更多相關js腳本加載失敗內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
php register_shutdown_function函數詳解
register_shutdown_function() 函數可實現當程序執(zhí)行完成后執(zhí)行的函數,其功能為可實現程序執(zhí)行完成的后續(xù)操作,需要的朋友可以參考下2017-07-07一文詳解JavaScript的事件監(jiān)聽(最新整理)
Web頁面需要經常和用戶之間進行交互,而交互的過程中我們可能想要捕捉這個交互的過程,比如用戶點擊了某個按鈕、用戶在輸入框里面輸入了某個文本、用戶鼠標經過了某個位置,下面介紹下JavaScript的事件監(jiān)聽,感興趣的朋友一起看看吧2024-01-01