2013-11-26 50 views
5

我爲幾個網站提供了一個JavaScript小部件,它們是異步加載的。我的小部件反過來需要加載另一方提供的腳本,在我的控制之外。第三方腳本無法加載後運行一段JavaScript

有幾種方法可以檢查該腳本是否已成功加載。但是,如果腳本加載失敗,我還需要運行不同的代碼。

不工作的最明顯的工具包括:

  • 我不願意使用JavaScript庫,如jQuery。我需要一個非常小的腳本來減少我對使用我的小部件的網站的影響。

  • 我想盡快檢測到故障,所以使用計時器輪詢它是不可取的。不過,我不介意在舊瀏覽器上使用計時器作爲最後的手段。

  • 我發現<script>標記的onerror事件在某些主流瀏覽器中不可靠。 (這似乎取決於哪些附加軟件已安裝。)

  • 涉及document.write的任何內容都是正確的。 (除了這個方法是本質上是邪惡,我的代碼是異步這樣document.write可以做壞事的頁面加載。)

我有一個以前的解決方案,參與新加載<script>。在該iframe中,我設置了一個<body onload=...>事件處理程序,用於檢查<script onload=...>事件是否已經觸發。因爲<script>是初始文檔的一部分,不是以後異步注入的,onload僅在使用<script>標記完成網絡層後纔會觸發。

但是,現在我需要腳本來加載父文檔;它不能再在iframe中。因此,只要網絡層已經放棄嘗試獲取腳本,我就需要一種不同的方式來觸發代碼。

我讀了「Deep dive into the murky waters of script loading」,試圖找出我可以在不同瀏覽器中使用的順序保證。

如果我的理解有記載的技術:

  • 我需要把我的失敗處理代碼在一個單獨的文件.js
  • 然後,在某些瀏覽器上,我可以確保只有在第三方腳本運行或失敗後,我的代碼才能運行。這就要求支持任何瀏覽器:
    • 通過DOM的<script async>屬性設置爲false,
    • 或IE 6+使用<script onreadystatechange=...>

儘管看async support table,我不能告訴我是否可以依靠腳本排序足夠的瀏覽器這是可行的。

那麼我怎樣才能可靠地處理故障加載腳本我不控制?

+0

如何檢查腳本中是否存在某些內容。就像腳本包含某個對象一樣,查找那個 –

+0

@CrayonViolent,很容易確定腳本已經加載。但是,我需要知道何時檢查。如果我檢查得太快,腳本甚至不會被下載。我需要知道如何區分「尚未裝載」和「因爲放棄而永遠不會裝載」。如果我可以確定我的支票在腳本處理完成後運行,那麼我就全部設置好了。 –

+0

好吧,在腳本中檢查一個獨特的東西將是你最可靠的方法。但我真的不認爲有一種方法可以在x時間內每隔100ms左右使用'setTimeout'並在此之後放棄。這就是我在這樣的情況下所做的,到目前爲止我還沒有找到更好的方法。我現在不認爲存在:/ –

回答

2

我相信我已經解決了我問的問題,但事實證明這並不能解決我實際遇到的問題。好吧。這是我的解決方案:

我們希望在瀏覽器完成嘗試加載第三方腳本後運行一些代碼,以便我們可以檢查它是否成功加載。我們通過限制後備腳本的負載僅在第三方腳本運行或失敗後才能實現。然後,回退腳本可以檢查第三方腳本是否創建了它應該設置的全局變量。

跨瀏覽器的按順序腳本加載啓發http://www.html5rocks.com/en/tutorials/speed/script-loading/

var fallbackLoader = doc.createElement(script), 
    thirdPartyLoader = doc.createElement(script), 
    thirdPartySrc = '<URL to third party script>', 
    firstScript = doc.getElementsByTagName(script)[0]; 

// Doesn't matter when we fetch the fallback script, as long as 
// it doesn't run early, so just set src once. 
fallbackLoader.src = '<URL to fallback script>'; 

// IE starts fetching the fallback script here. 

if('async' in firstScript) { 
    // Browser support for script.async: 
    // http://caniuse.com/#search=async 
    // 
    // By declaring both script tags non-async, we assert 
    // that they need to run in the order that they're added 
    // to the DOM. 
    fallbackLoader.async = thirdPartyLoader.async = false; 
    thirdPartyLoader.src = thirdPartySrc; 
    doc.head.appendChild(thirdPartyLoader); 
    doc.head.appendChild(fallbackLoader); 
} else if(firstScript.readyState) { 
    // Use readyState for IE 6-9. (IE 10+ supports async.) 
    // This lets us fetch both scripts but refrain from 
    // running them until we know that the fetch attempt has 
    // finished for the first one. 
    thirdPartyLoader.onreadystatechange = function() { 
     if(thirdPartyLoader.readyState == 'loaded') { 
      thirdPartyLoader.onreadystatechange = null; 
      // The script-loading tutorial comments: 
      // "can't just appendChild, old IE bug 
      // if element isn't closed" 
      firstScript.parentNode.insertBefore(thirdPartyLoader, firstScript); 
      firstScript.parentNode.insertBefore(fallbackLoader, firstScript); 
     } 
    }; 
    // Don't set src until we've attached the 
    // readystatechange handler, or we could miss the event. 
    thirdPartyLoader.src = thirdPartySrc; 
} else { 
    // If the browser doesn't support async or readyState, we 
    // just won't worry about the case where script loading 
    // fails. This is <14% of browsers worldwide according to 
    // caniuse.com, and hopefully script loading will succeed 
    // often enough for them that this isn't a problem. 
    // 
    // If that isn't good enough, you might try setting an 
    // onerror listener in this case. That still may not work, 
    // but might get another small percentage of old browsers. 
    // See 
    // http://blog.lexspoon.org/2009/12/detecting-download-failures-with-script.html 
    thirdPartyLoader.src = thirdPartySrc; 
    firstScript.parentNode.insertBefore(thirdPartyLoader, firstScript); 
} 
0

您是否考慮過使用窗口的onerror處理程序?這可以讓你發現大多數錯誤發生時,你可以採取適當的行動。作爲沒有被這種方式捕捉到的任何問題的回退,你也可以用try/catch來保護你自己的代碼。

您也應該檢查第三方腳本實際加載:

<script type="text/javascript" onload="loaded=1" src="thirdparty.js"></script> 

然後檢查是否加載:

window.onload = function myLoadHandler() { 
    if (loaded == null) { 
    // The script doesn't exist or couldn't be loaded! 
    } 
} 

您可以檢查使用url參數,腳本導致錯誤。

window.onerror = function myErrorHandler(errorMsg, url, lineNumber) { 
    if (url == third_party_script_url) { 
    // Do alternate code 
    } else { 
    return false; // Do default error handling 
    } 
} 
+0

你能給出一個可移植檢測腳本錯誤的例子,但只有來自特定'

  • 11. Javascript - 動態加載HTML片段並運行腳本
  • 12. 無法運行PowerShell卸載腳本
  • 13. 運行PHP腳本加載
  • 14. 如何從第三方腳本中分離頁面加載?
  • 15. bash腳本無法讀取第一行
  • 16. ajax加載後運行javascript
  • 17. Bootstrap JavaScript已加載但無法運行
  • 18. 從第三方腳本加載彈出窗口後替換href值
  • 19. 第二次運行後返回空白的jQuery加載()方法
  • 20. NPAPI加載第三方DLL
  • 21. 如何在內部腳本完全加載後運行腳本?
  • 22. 在ajax載入頁面後無法執行javascript腳本
  • 23. 在HTML中使用2個腳本:第一個javascript將不會在第二個腳本後運行javascript
  • 24. 無法使用jquery從第三方腳本中移除div
  • 25. CasperJS「無法加載腳本」
  • 26. 無法運行python腳本
  • 27. 無法運行lein腳本
  • 28. 無法運行shell腳本
  • 29. 無法運行sql腳本
  • 30. 無法運行shell腳本