2016-01-24 59 views
8

我遇到了HTML注入已加載的DOM的問題,其中腳本文件下載後正在加載內聯javascript。據我所知,這不應該是異步的,內聯腳本應該在腳本文件之後執行。如果域名與調用頁面相同,但是使用CDN或甚至子域名執行相同的操作,這將起作用。有什麼我應該做的,以重做我如何稱呼這些?我發誓之前工作過,因爲我已經開了一個多星期的CDN,但也許我從來沒有發現過這個問題。腳本文件在內聯腳本中執行後使用CDN或外部域在HTML注入

控制檯

Loading Inline Script 
VM1400:3 Uncaught TypeError: Cannot read property 'init' of undefined(anonymous function) 
app.members.event.js?v=204&_=1453644424985:5 Loading Script File 
app.members.event.js?v=204&_=1453644424985:71 Finished Script File 

的Javascript

<script type="text/javascript" src="https://test.azureedge.net/Areas/Directors/scripts/app.members.event.js?v=204"></script> 
<script type="text/javascript"> 
console.log('Loading Inline Script'); 
    app.viewModel.members.event.init(); 
console.log('Finished Inline Script'); 
+0

我覺得有什麼不對/從你的JS代碼失蹤。你有 });沒有開放括號。 –

+0

我只是修剪它,代碼沒有錯,因爲它發生在其他頁面上。 –

+0

顯然我錯過了你的觀點,一旦這個問題被改變,將刪除我的downvote,只是@ -me。我的猜測是你的代碼錯了,或者你的腳本網址被破壞了。 –

回答

3

的一種方法是使用jquery's getScript()功能。

但最好是,您可以使用本機JavaScript加載腳本文件,然後運行內聯腳本。

也許我還沒有明確的理解這個問題。

編輯: 這是關於腳本元素的HTML5規範的一句話。

如果該元素具有一個src內容屬性,執行這些子步驟:

讓SRC是元素的src屬性的值。

如果src是空字符串,則排隊任務以在元素處觸發名爲 錯誤的簡單事件,然後中止這些步驟。

解析相對於元素的src。

如果上一步失敗,則排隊任務以在元素處觸發名爲 錯誤的簡單事件,然後中止這些步驟。

做一個潛在的啓用CORS,與選擇的模式是元素的crossorigin 內容屬性的當前狀態,獲取結果的絕對URL的, ,原點是腳本元素的 文件的原點,默認原點行爲設置爲污點。

以這種方式獲得的資源可以是CORS-同源 或CORS-交叉來源。這隻會影響錯誤報告的發生。

出於性能原因,用戶代理可以開始只要src屬性被設置獲取腳本(如上所定義 ),相反,在 希望元件將被插入到該文檔(和該 crossorigin屬性在此期間不會改變數值)。無論哪種方式, 一旦元素被插入到文檔中,加載必須有 按照此步驟中的描述啓動。如果UA執行預取,但該元素從未插入到文檔中,或者動態更改了 src屬性,或者動態更改了交叉索引屬性 ,則用戶代理將不會執行如此獲得的腳本 ,並且取水過程將會被有效地浪費掉 。

然後,第一的描述的情況 下列選項必須遵循:

如果該元素具有src屬性,而元素有一個延遲 屬性和元素已被標記爲「解析器插入」,並且 該元素沒有異步屬性該元素必須被添加 到腳本列表的末尾,在文檔 完成與 創建的解析器的文檔相關聯的解析時將執行該腳本元素。

,關於任務隊列的網絡任務源的地方,一旦 的取算法已完成必須設置元素的「準備 是解析器執行的」標誌的任務。解析器將處理執行腳本。

如果元件具有src屬性,並且元件已被標記 爲「解析器插入」,而元件不具有一個異步屬性 的元素是文檔的待決解析阻擋腳本 創建元素的解析器。 (只能有每個文檔的一個這樣的 腳本在同一時間。)

,一旦 的取算法已經完成了任務隊列的網絡任務源場所必須設置元素的「準備 是解析器任務執行「標誌。解析器將處理執行腳本。

如果元素沒有src屬性,元素一直 標記爲「解析器插入」,並表明創建 腳本解析器是XML解析器或者它是一個HTML解析器其腳本嵌套 級別不大於1,並且創建腳本元素的HTML解析器或 XML解析器的文檔具有 阻止腳本的樣式表元素是解析器的Document的 的暫掛解析攔截腳本創造了這個元素。 (一次只能得到 每個文檔一個這樣的腳本。)

設置元素的「準備好解析器執行」標誌。解析器將會執行腳本 。

如果該元素具有src屬性,不具備異步特性, 和不具備「強制異步」標誌設置的元素必須添加 到將執行腳本的列表的末尾爲了儘快與 關聯的腳本元素的文檔在 時刻準備腳本算法開始。

的任務,一旦 的取算法已經完成了必須執行下列步驟的任務隊列中的網絡任務源的地方:

如果元素是不是現在在腳本 列表中的第一個元素將盡快按順序執行,並在上面添加 ,然後將該元素標記爲準備就緒,但會中止這些步驟,但不執行該腳本 。

執行:執行該腳本列表中的第一個腳本 元素所對應的腳本塊,該腳本將盡快按照 的順序執行。

從此腳本列表中刪除第一個元素,它將盡快按順序執行 。

如果將爲了儘快執行儘可能 仍然不爲空,首先進入已經被標記爲 準備腳本的清單,然後跳回一步標記執行。

如果該元素具有src屬性的元素必須被添加到 組將在時儘快腳本元素的文檔 的執行編寫一個腳本算法 啓動腳本。

,關於任務隊列的網絡任務源的地方,一旦 的取算法已經完成了必須執行的腳本塊和 然後從組腳本,將立即執行 儘可能刪除元素的任務。

否則即使其他腳本已經在執行,用戶代理也必須立即執行腳本塊 。獲取外部 腳本必須延遲元素文檔的加載事件,直到已獲取(上面定義的)資源 運行後由網絡任務源排隊的 任務。

從這我認爲你的「外部」文件加載後的內聯腳本塊。因此,我將使用jquery中的「getScript()」函數來確保腳本在內聯腳本塊之前加載。

+0

不,我相信你是在正確的軌道上..但是,爲什麼它只與當前的域名一起工作很好,但如果我指出它不... –

+0

我認爲它與響應時間有關。這些文件是否應該在同一位置?緩存也可能與它有關。我看到你在引用一個?v = 204,你是否在改變這個數字? – brannmar

+0

那麼,如果他們有相同的域,是的,他們在同一臺服務器上。如果我更新到一個子域,他們仍然在同一臺服務器上。如果我更新到CDN當然是一個不同的服務器。除非我明確告訴它,否則版本不會更改。我同意它的響應時間,但不應該在腳本執行之前先執行腳本。 –

0

我有兩個理論:

  1. 可能是有什麼東西在多數民衆贊成延遲app.viewModel.members對象的創建外部腳本(超時或一個事件處理程序,需要一段時間才能履行)。這可以通過在內聯腳本中設置一個很長的超時(f.i. 5000 + ms),然後檢查模型對象是否存在來輕鬆測試。

  2. 加載相同的原始腳本時會出現一些時髦現象。

在這種情況下,你可以嘗試是這樣做耽誤您的嵌入式腳本的執行以下操作:

<script type="text/javascript"> 
document.addEventListener("DOMContentLoaded", function(event) { 
    app.viewModel.members.event.init(); 
}); 
</script> 

或者只是把你的內嵌代碼在外部.js文件,並與調用它'deferred'標誌:

<script type="text/javascript" src="https://test.azureedge.net/Areas/Directors/scripts/app.members.event.js?v=204"></script> 
<script type="text/javascript" src="{link-to-external-js-file}" defer></script> 
0

這是注射scenerio中的一個常見問題。這是由於腳本可用性的可變延遲以及各種瀏覽器上的並行和不同實現。

根據源代碼是否可用於編輯以及腳本文件之間是否存在超過2個依賴關係,有3個選項。

選項1.使用推遲腳本標籤

這個選項屬性可以使用,如果這兩個腳本是遠程的(即不內聯)

「推遲」表示在瀏覽器中腳本必須在文檔解析後執行(從MDN引用)。這僅適用於具有「src」屬性的遠程(非內聯)腳本。

https://html.spec.whatwg.org/multipage/scripting.html#attr-script-defer

你可以使用它像下面。

defer是支持主流的瀏覽器,我驗證在Chrome,火狐,對Tizen的Webkit,和Safari:

https://developer.mozilla.org/en/docs/Web/HTML/Element/script#Browser_compatibility

爲了提供以上的情況下具體的例子,請參考下面。請注意,以下內容已在Firefox,Chrome,IE11,iPhone上的Safari和Tizen上的Webkit上驗證。

案例1:

很多Javascript文件 - 所有獨立:

如果不存在依賴關係中, 「推遲」 屬性允許的HTML被加載迅速。該腳本在下載後接管,沒有問題(假設載入等被照顧)。

案例2:

兩個JavaScript文件test1.js和test2.js - 一個依賴於其它:

如果test2.js取決於test1.js的加載,那麼test2.js腳本標記「only」應該具有defer屬性。

這種用法在

http://www.gpupowered.org/loadtest/2_defer.html

使用不當所示顯示在

http://www.gpupowered.org/loadtest/no_defer.html(這兩個腳本沒有延遲的標籤 - 這失敗) http://www.gpupowered.org/loadtest/all_defer.html(有推遲標記兩個腳本 - 這也失敗)

不工作的異步使用是,

http://gpupowered.org/loadtest/2_async.html(此失敗)

「推遲」不符合需求的地方在哪裏?

如果功能被分割爲多個JS文件(比如說n),並且在「n」個文件可以開始處理某些變量之前需要下載所有「n-1」,即使「defer」屬性可能是呈現在所有腳本源標籤上,因爲它們被接收的順序是不確定的,所以它被呈現爲不相關的。

更多的背景上的延遲和延遲加載的各種選項(不列入覆蓋多延遲情況) http://www.html5rocks.com/en/tutorials/speed/script-loading/

https://developer.mozilla.org/en/docs/Web/HTML/Element/script

選項2:使用狀態變量

此選項可以如果可以將一些額外的狀態變量添加到這兩個javascript源文件中,則可以使用它

該方法依賴於依賴js文件中的命名變量以及使用依賴文件的js文件中的命名函數。如果在用戶文件嘗試訪問其功能時未依次加載相關文件,它將退出並在真正加載時被回調。

這在以下html文件中演示。

http://gpupowered.org/loadtest/variable.html(正常工作)

如果加載需要反覆出現此選項不起作用(即,相同的名稱等的多個文件加載)。

選項3:本地腳本裝載機

在這種情況下,存在具有彼此之間的依賴關係的多個JavaScript文件。

對於使用延遲或異步或其他規範提供的標籤的情況,沒有解決方案。對於我在gpupowered.org的遠程實驗中使用的用例,我必須使用XMLHttpRequest實現我自己的本地腳本加載器,其源代碼在下面的鏈接中提供。這使用工作線程,因爲我擁有的一些紋理相當大。回調函數可以用來根據應用程序需要實現依賴性邏輯。例如,保持所有加載腳本的計數,然後觸發完整的執行等。

https://github.com/prabindh/gpupowered.gl/blob/master/worker/worker_object_loader.js

jQuery的腳本加載器使用HTTP請求爲好,但如果它使用一個工人裝載我沒有檢查。 https://api.jquery.com/jquery.getscript/

0

使用此:

<script type="text/javascript" src="https://test.azureedge.net/Areas/Directors/scripts/app.members.event.js?v=204&onload=onloadCallback"></script 

<script type="text/javascript">function onloadCallback(){ 
app.viewModel.members.event.init();}</script> 
0
function onloadCallback(){ 
    app.viewModel.members.event.init(); 
}