整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          網頁文件加載失敗如何重試

          文由 ChatMoney團隊出品

          在我們開發網站應用時,我們可能會遇到腳本加載失敗的情況,導致腳本加載失敗的原因有很多,比如用戶的網絡問題、終端設備問題、用戶瀏覽器版本等諸多因素。

          解決方案

          在 JavaScript 中,我們可以創建一個監聽來監聽腳本加載失敗的情況,然后針對加載失敗的腳本進行重新加載。

          重新加載的方案,一般是通過更換域名來解決。我們給每個腳本添加一個映射關系表,用來在加載失敗時匹配新的域名進行重試。

          具體的解決方案,下面我一步一步講解,另外希望大家可以仔細閱讀注釋中的內容

          <!DOCTYPE html>
          <html lang="en">
            <head>
              <meta charset="UTF-8" />
              <meta name="viewport" content="width=device-width, initial-scale=1.0" />
              <title>腳本加載失敗如何重試</title>
              <script>
                window.addEventListener(
                  "error", // 監聽全局錯誤
                  function (e) {
                    console.log(e);
                  },
                  true // 由于腳本加載失敗不會冒泡,所以我們要在捕獲階段進行監聽
                );
              </script>
            </head>
            <body>
              <script src="https://www.zowlsat.com/api/1.js"></script>
              <script src="https://www.qqqqqqq.com/api/2.js"></script>
              <script src="https://www.zowlsat.com/api/3.js"></script>
            </body>
          </html>

          此時我們可以在瀏覽器控制臺看到以下效果

          但是這個監聽方法會監聽到很多其他的錯誤,我們只需要監聽腳本加載失敗的錯誤,所以我們要通過這個監聽事件的參數 e 來判斷了

          根據上圖我們可以發現,普通錯誤的類型是 ErrorEvent,而腳本加載失敗的類型是 Event,并且他的 target 會指向 script 標簽,所以我們根據這個區別過濾掉其他的錯誤,這樣剩下的情況才是我們需要處理的。

          window.addEventListener(
            "error",
            function (e) {
              if (e.target.tagName !== "SCRIPT" || e instanceof ErrorEvent) return;
              console.log(e);
            },
            true
          );

          接下來就是如何來實現重新加載,我們先給需要重新加載的域名建立一個映射關系,用于替換映射關系表中的域名。然后就是挨個匹配,當還是加載失敗時繼續匹配下一個,直到成功為止。

          const domainList = ["www.aaaaa.com", "www.bbbbb.com", "www.zowlsat.com"];
          const retry = {};
          window.addEventListener(
            "error",
            function (e) {
              if (e.target.tagName !== "SCRIPT" || e instanceof ErrorEvent) return;
              // 創建一個URL對象
              const url = new URL(e.target.src);
              // 獲取文件路徑
              const key = url.pathname;
              // 假如映射表中沒有這個文件路徑,那么就初始化一個映射鍵
              if (!(key in retry)) {
                retry[key] = 0;
              }
              // 假如匹配完整個映射表都沒重新加載成功,則放棄
              const index = retry[key];
              if (index >= domainList.length) {
                return;
              }
              // 獲取新的完整路徑
              const domain = domainList[index];
              // 替換域名
              url.host = domain;
              // 創建新的script標簽
              const script = document.createElement("script");
              script.src = url.toString();
              // 將新的script標簽追加到加載失敗的script標簽之前
              document.body.insertBefore(script, e.target);
              retry[key]++;
            },
            true // 由于腳本加載失敗不會冒泡,所以我們要在捕獲階段進行監聽
          );

          到此為止,我們功能已經基本實現,效果如下圖

          但是有一個很關鍵的問題,就是假如我 2.js 這個文件中的內容,在 3.js 中要使用,那這樣的話,2.js 就必須加載到 3.js 之前,否則就會報錯。此時,我們就需要在 2.js 加載失敗時,阻塞瀏覽器的解析,知道重新加載完成或者放棄重新加載時,再繼續渲染之后的內容。

          那這樣的話我們該怎么做呢?


          其實很簡單,在我們入門 js 時就學到過一個知識點,就是使用document.write

          document.write這個方法在解析期間使用的話,會阻塞瀏覽器的解析,而我們現在就是需要阻塞瀏覽器解析,那此時我們只需要將創建 script 標簽的方法更換為document.write方法即可。


          修改之后的代碼如下:

          const domainList = ["www.aaaaa.com", "www.bbbbb.com", "www.zowlsat.com"];
          const retry = {};
          window.addEventListener(
            "error",
            function (e) {
              if (e.target.tagName !== "SCRIPT" || e instanceof ErrorEvent) return;
              const url = new URL(e.target.src);
              const key = url.pathname;
              if (!(key in retry)) {
                retry[key] = 0;
              }
              const index = retry[key];
              if (index >= domainList.length) {
                return;
              }
              const domain = domainList[index];
              url.host = domain;
              // 此處加上轉譯是因為防止編譯器識別script標簽為結束標簽報錯
              document.write(`\<script src="${url.toString()}">\<\/script>`);
              //   const script = document.createElement("script");
              //   script.src = url.toString();
              //   document.body.insertBefore(script, e.target);
              retry[key]++;
            },
            true
          );

          現在我們再打開控制臺查看,現在js文件按它原來的順序執行了,這樣既不會改變原有的代碼邏輯,又可以在可控范圍內進行重新加載。

          效果如下圖:

          以上是簡單實現了一個js文件重新加載錯誤的方案,其實這個方案也可以運用到其他很多類型的文件,不限于js文件。

          然后我們還需要更加細化這個方法的話,我們可能還需要考慮到這個script標簽是否帶有async、defer等屬性,還有諸多需要考慮的點,但是沿著這個方向解決的話,大體是沒有問題的。

          關于我們

          本文由ChatMoney團隊出品,ChatMoney專注于AI應用落地與變現,我們提供全套、持續更新的AI源碼系統與可執行的變現方案,致力于幫助更多人利用AI來變現,歡迎進入ChatMoney獲取更多AI變現方案!

          們從播放開始,因為觀看直播最重要的一個環節就是打開播放器,很多問題的直接反饋也是來自觀眾端。

          導致播放失敗的原因,有很多種,不一定是播放器本身的問題,不過通過播放器,我們很容易反過來排查服務端或者推流端的問題。下面我們會從播放失敗的表現、播放問題排查工具、常見問題分析等多個方面展開討論。

          1. 播放失敗的表現

          播放失敗的表現總結下來包括但不限于以下這些:

          - 界面上一直顯示 “加載中”,或者提示播放失敗的錯誤

          - 播放畫面卡死不動,但 UI 按鈕可以點擊

          - 有聲音沒有畫面,有畫面沒有聲音

          這里并不討論如播放卡頓、音畫不同步、馬賽克、延時、花屏等問題,這些話題,我們將會在后續的文章中探討,本文重點關注的是:為啥無法順利 “打開” 直播流 ?

          2. 播放問題的排查工具

          一旦我們遇到視頻播放不了,第一件事,就是要找幾個別的播放器也播放看看,做一下對比測試,或者對碼流做一些基礎分析,以便更好地定位問題的源頭,各個平臺比較常見的播放/分析工具有如下幾個:

          2.1 命令行工具

          ffplay,ffprobe,mediainfo,hls-analyzer 等

          2.2 網頁端工具

          http://www.cutv.com/demo/live_test.swf

          SRS

          2.3 App 應用

          vlc,vplayer,mxplayer 等

          2.4 Windows 工具

          mp4info,FlvParse,FLVMeta,Elecard StreamEye Studio 等


          音視頻開發學習地址:C/C++Linux服務器開發/后臺架構師【零聲教育】-學習視頻教程-騰訊課堂

          【文章福利】:小編整理了一些個人覺得比較好的學習書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!~點擊832218493加入(需要自取)

          3. 常見播放失敗問題排查

          3.1 基礎概念

          從給播放器傳入播放地址,到播放畫面顯示出來,一般有如下幾個步驟:

          - DNS 解析,將播放地址中的域名解析為對應的服務器 ip 地址

          - 連接服務器,完成 http 請求或者 rtmp 握手過程

          - 接收服務器發送的數據,解協議解封裝,拿到音視頻數據解碼播放

          任何一個環節出了問題,都有可能導致播放失敗,不同的協議,由于協議層原因,播放報錯往往不太一樣,我們下面的討論,主要以 RTMP/HTTP 這兩種協議為主,假設正常的播放測試地址如下:

          香港衛視的 RTMP 直播流:rtmp://live.hkstv.hk.lxdns.com/live/hks

          W3C School 的測試 mp4 流:http://www.w3school.com.cn/i/movie.mp4

          3.2 域名解析失敗

          如果播放地址的域名無法解析,會導致播放失敗,一般斷網了或者域名無效,則播放的時候,會有類似如下報錯:

          $ ffplay rtmp://live.hkstv.hk.lxdns.com1/live/hks
          Failed to resolve hostname live.hkstv.hk.lxdns.com1: nodename nor servname provided, or not knownFailed to resolve hostname live.hkstv.hk.lxdns.com1: No address associated with hostname

          當然,如果有網絡,但是域名解析失敗,一般 ISP 運營商可能會返回一些類似 404 頁面,或者跳轉到其他的默認網頁,因此,對于 HLS,HTTP-FLV,HTTP-mp4 等碼流,會因為讀到一些 “臟數據” 從而返回一些其他的錯誤,例如:

          $ ffplay http://www.w3school2.com.cn1/i/movie.m3u8
          http://www.w3school2.com.cn1/i/movie.m3u8: Operation timed out
          $ ffplay http://www.w3school2.com.cn1/i/movie.mp4
          http://www.w3school2.com.cn1/i/movie.mp4: Invalid data found when processing input

          遇到這類錯誤,一般可以通過 ping 一下域名試試,看看是否可以 ping 通,如果 ping 不通,則可能要檢查下域名解析的配置了。

          3.3 服務器連接失敗

          如果域名正確,并且有網絡連接的狀態,多半是可以正常解析出服務器 ip 地址的,但是依然有連接失敗的可能,比如,這臺服務器相應的服務掛掉了,或者并沒有在相應的端口提供服務,從而導致播放器連接失敗,類似問題的報錯如下:

          $ ffplay rtmp://www.jhuster.com/live/hks
          Cannot open connection tcp://www.jhuster.com:1935rtmp://www.jhuster.com/live/hks: Operation timed out

          因為 www.jhuster.com 對應的服務器并沒有提供 rtmp 拉流服務,因此通過 1935 連接該服務器會失敗。

          $ ffplay https://www.w3school.com.cn/i/movie.mp4
          Connection to tcp://www.w3school.com.cn:443 failed: Connection refused

          因為 w3school 在線教程 并不支持 https 訪問,因此通過 443 接口請求 https 連接失敗

          當然,也有可能是這臺服務器雖然提供了 rtmp 拉流服務但是宕機了,因此,我們需要通過 dig 命令確定最終訪問的是哪一臺服務器,并排查下該服務器為什么無法連接,當然,最好是修改下 ffpmeg 源碼,把解析出來的服務器 ip 地址打印出來,這樣就可以直接看到所連接的服務器地址了。

          3.4 請求的資源不存在

          對于 http 協議的直播地址,請求的播放資源不存在,返回的錯誤還是比較快的,比如:

          $ ffplay http://jhuster.com/live/hks.mp4
          Page not found · GitHub Pages Server returned 404 Not Found
          
          $ ffplay http://www.w3school2.com.cn/i/movie2.mp4
          http://www.w3school2.com.cn/i/movie2.mp4: Invalid data found when processing input


          注:由于讀到 ISP 運營商返回的跳轉頁面的 “臟數據”,因此也有可能返回上面這種錯誤

          而 RTMP 直播協議,跟 HTTP 協議的播放,有著一個很大的不同,就是播放器請求的數據,并不一定 “存放” 在服務器,因此,服務器無法簡單通過 URI 定位不到則返回 404,這些數據是在 RTMP 握手之后,由生產端逐步產生并由服務器轉發到客戶端,因此很難簡單判斷說 “資源不存在”。

          通常 RTMP 協議的直播流,如果推流端沒有推流了,播放器這邊一般是讀數據超時后才會返回錯誤,例如:

          $ ffplay rtmp://live.hkstv.hk.lxdns.com/live/hks1
          rtmp://live.hkstv.hk.lxdns.com/live/hks1: Input/output error


          3.4 不支持的格式

          視頻流的采用的網絡協議、編碼格式、封裝格式有很多種,網絡協議比如 http/https/rtmp/rtsp 等等,編碼格式比如 h.264,mpeg4,aac,speex 等等,封裝格式比如 flv,mp4,avi,rmvb 等等,這些協議和格式的流,都是需要播放器專門添加支持的,因此,播放器遇到不支持的協議或者格式,也會導致播放失敗,如下所示:

          https://www.jhuster.com/xxxx.mp4 Protocol not found
          http://www.jhuster.com/xxxx.rmvb Invalid data found when processing input

          3.5 只有音頻沒有視頻,或者只有視頻沒有音頻

          出現該錯誤的原因可能有如下幾點:

          - 音頻/視頻的編碼格式不支持,導致解碼失敗

          - 音頻/視頻的數據內容異常,導致解碼失敗

          - 基于 ffmpeg 的播放器的 `probesize` 設置太小,導致解析碼流信息不足

          - 碼流/文件本身的前半段只有音頻沒有視頻,或者只有視頻沒有音頻

          這個問題播放啟動流程已經完成,只是出現了畫面缺失、或者音頻缺失,也算是一種播放失敗,限于本文篇幅,該問題后面會抽出專門的章節來分析。

          3.6 其他播放失敗


          上面只分析了常見的播放失敗問題,其實導致播放失敗的原因還有千千萬萬種,這里無法一一都列出來,不過通過 ffplay 的報錯,就知道大概的原因,再聯合服務端一起調試調試,一般都是可以找到根本原因的。下面是 ffmpeg 常見的錯誤分類:

          http://ffmpeg.org/doxygen/trunk/error_8h_source.html

          -----------------------------------

          ?著作權歸作者所有:來自51CTO博客作者Jhuster的原創作品,請聯系作者獲取轉載授權,否則將追究法律責任

          直播疑難雜癥排查(1)— 播放失敗

          直播疑難雜癥排查(1)- 播放失敗

          很多剛剛接觸css的新手有時會遇到css加載失敗這個問題,但測試時,網頁上沒有顯示該樣式的問題,這就說明CSS加載失敗了。出現這種狀況一般是因為的css路徑書寫錯,或者是在瀏覽器中禁止掉了css的加載,可以重新啟動瀏覽器刷新,在文件中css的調用,一般都是通過link加上你的路徑來實現,具體可以看下代碼:

          <!DOCTYPE html><html><head><meta charset="UTF-8">
          <title>index</title>
          <link rel='stylesheet' type='text/css' href='./css/index1.css'>
          //注意好文件名的書寫就沒問題了。
          


          造成css加載失敗的原因有很多,這可能跟你代碼出錯,瀏覽器、路徑、編碼等等都是有關聯的。所以在具體情況具體分析。最常見的失敗原因有以下幾類:

          1.網絡原因

          IIS空間不足、瀏覽者網速慢、空間速度慢等網絡因素是造成CSS加載失敗的原因之一,其具體表現為:當我們打開網頁時,網頁布局完整,但卻沒有任何布局樣式顯示。

          2.路徑錯誤或者代碼不兼容

          如果網頁打開時,沒有顯示CSS設定的樣式,只以原始狀態顯示。那么就可能是我們CSS文件路徑出錯或者CSS代碼不兼容了。

          3.if造成失敗

          第三個原因是,我們編在寫CSS時,可能使用了if判斷語句對什么瀏覽器調用什么CSS文件時疏忽造成if調用的混亂,導致在某些瀏覽器上能正常顯示,在某些瀏覽器上不能正常顯示。對于這個原因,解決方法就是好好檢查造成CSS加載失敗的if判斷設置。

          4.另類CSS加載失敗

          何為另類CSS加載失敗?這是由于我們本身的CSS代碼寫法有問題,沒有設置好造成在各瀏覽器顯示不同布局差距效果。在CSS里面,我們稱為css hack。


          5、瀏覽器導致

          在Chrome瀏覽器的錯誤控制臺下看看css文件有沒有加載進來,確定已加載的話,檢查元素的類名與CSS中定義的類名是否相同。可能局限于ie瀏覽器,你用谷歌瀏覽器就會出現錯誤。所以嘗試換個瀏覽器,然后等會在用,也可能修復故障。

          6、編碼不對

          如果不是上述問題則看一看你的CSS文件的字符集是否和你的調用CSS文件的網頁的字符集是否一致,就是charset屬性那里。在你使用瀏覽器進行瀏覽效果的時候,ie瀏覽器中菜單欄上有一個“查看--編碼”,在查看編碼上面UTF-8或者GBK看看是不是同一個編碼。可能是編碼不一致所造成。

          以上就是造成CSS加載失敗最常見的六大原因。我們了解這些原因后,如果在實際操作中遇到類似問題,便可逐一對照排查,對癥下藥解決問題。


          主站蜘蛛池模板: 伦精品一区二区三区视频| 国产成人av一区二区三区不卡 | 国产精品久久亚洲一区二区| 亚洲av日韩综合一区久热| 日韩美女视频一区| 一区精品麻豆入口| 无码人妻久久久一区二区三区| 好爽毛片一区二区三区四无码三飞| 国产在线精品一区二区高清不卡| 无码少妇一区二区性色AV| 精品无码国产一区二区三区51安 | 国产情侣一区二区| www一区二区三区| 人妻AV中文字幕一区二区三区| 欧美日韩国产免费一区二区三区 | 成人h动漫精品一区二区无码| 日韩精品无码久久一区二区三| 无码乱人伦一区二区亚洲一 | 熟妇人妻系列av无码一区二区| 91精品国产一区| 一区二区免费在线观看| 久久伊人精品一区二区三区| 秋霞电影网一区二区三区| 亚洲av午夜福利精品一区人妖| 精品国产亚洲第一区二区三区| 久久免费国产精品一区二区| 成人在线观看一区| 久久久久99人妻一区二区三区| 国产剧情一区二区| bt7086福利一区国产| 成人无码AV一区二区| 精品国产一区二区三区久| 99久久人妻精品免费一区| 国产伦一区二区三区高清| 国产一区二区三区韩国女主播| 中文人妻av高清一区二区| 美女AV一区二区三区| 亚洲AV香蕉一区区二区三区| 国产色综合一区二区三区| 亚洲国产一区二区三区| 无码人妻一区二区三区av|