2011-04-16 31 views
1

我正在實現異步加載腳本的功能。 XHR完成後,我將代碼插入文檔並調用回調方法。回調方法使用該動態加載的代碼。在異步嵌入腳本後需要使用window.onReady()嗎?

我想知道的是,我的回調在附加腳本解析之前被調用嗎?我是否需要使用window.onReady()並讓瀏覽器引擎解析附加的腳本並觸發window.onReady(),然後調用我的回調方法?

請不要告訴我使用<your favority library here>,因爲我正在這樣學習。

編輯:或者,我應該插入一個腳本元素與srcasync設置,並聽取腳本元素的readystatechange事件?

+0

如何將代碼插入到文檔中? – 2011-04-16 18:46:00

+0

什麼事件觸發您的回調函數? – 2011-04-16 18:46:29

+0

什麼是'window.onReady()'? – 2011-04-16 18:53:07

回答

1

這真的取決於你如何加載它。

您可以加載一個腳本,然後在加載它之後只需eval()responseText。

或者,你也可以document.createElement('script'),然後調用回調方法。

Pusuedocode:

load_xhr('path/to/js', function onReady (responseText) { 

eval(responseText); 

//OR 

var script = document.createElement('script'); 

script.text = responseText; 

//Append element to DOM 

//THEN 

callback_method(); 

}); 

編輯:或者,我應該插入帶有src和異步集, 並聽取腳本元素的 readystatechange事件的腳本 元素?

如果你這樣做,瀏覽器的加載符號將顯示。如果您通過XHR加載它,用戶將不會注意到任何事情。

+0

不錯的「pusuedocode」。無論如何,我感興趣的是在腳本插入到DOM之後腳本是否總是被解析,或者是否存在任何問題。 – Tower 2011-04-16 19:49:55

+0

這裏有幾個問題:1.如果您通過XHR加載,除了支持CORS的網站和瀏覽器之外,您受到[SOP](http://en.wikipedia.org/wiki/Same_origin_policy)的限制, 。 2.「eval」與在全局上下文中加載腳本不同,在評估代碼的上下文中存在各種各樣的後果。更好的做法是創建一個'script'元素,即使你通過XHR加載代碼。 – 2011-04-16 20:42:53

+0

@rFactor,如果使用.text屬性,而不是.innerHTML屬性,腳本會立即被解析 – xaav 2011-04-16 22:00:34

1

或者,我應該插入帶有src和異步集的腳本元素,並聽取他們的腳本元素的readystatechange事件

最可靠的方法是插入一個script元素與src集(唐不設置asyncdefer,不需要)。對於腳本已經加載並分析的通知,做兩件事情之一:

  1. 該腳本告訴你當它準備。例如,讓它調用一個你已經在頁面上定義的函數。如果你控制你正在加載的腳本,這是最好的辦法。

    例(live copy):

    腳本:

    function foo() { 
        display("foo() called"); 
    } 
    callWhenReady(); 
    

    腳本加載它:

    var script; 
    display("Loading script " + url + "..."); 
    script = document.createElement('script'); 
    script.src = url; 
    document.body.appendChild(script); 
    
    function callWhenReady() { 
        display("Script says it's ready, calling foo..."); 
        foo(); 
    } 
    
  2. 使用自補賽setTimeout循環尋找一個符號該腳本定義(可能你知道一個,你想調用它)。或者你可以使用setInterval,但是這需要你跟蹤定時器句柄,坦率地說我更喜歡自我重新安排的控制。

    例(live copy):

    腳本(注意沒有回調):

    function foo() { 
        display("foo() called"); 
    } 
    

    加載腳本:

    var script; 
    display("Loading script " + url + "..."); 
    script = document.createElement('script'); 
    script.src = url; 
    document.body.appendChild(script); 
    watchFor('foo'); 
    
    function watchFor(fname) { 
        if (typeof foo === "function") { 
        display("foo detected! Calling..."); 
        foo(); 
        } 
        else { 
        // Not found yet, wait 
        setTimeout(function() { 
         watchFor(fname); 
        }, 50); 
        } 
    } 
    
  3. 更新:重新下方的評論:如果你真的知道什麼都沒有關於正在加載的腳本,並且您不能讓劇本呼叫您,但我不清楚爲什麼您需要接收該事件。 (如果你不知道它的全局符號,那麼你會怎麼做,所以不能調用它添加的任何函數?)但大多數瀏覽器都支持load事件script元素,對於那些不支持(早期的IE ,主要是),有readystatechange事件。對於這種情況,你可以使用這些材料的組合:(live copy

    例子:

    var script; 
    display("Loading script " + url + "..."); 
    script = document.createElement('script'); 
    script.onload = function() { 
        display("Script loaded (notification via load event). Calling foo just to prove it's loaded, but in the question we wouldn't know about the symbol do we wouldn't be able to call it."); 
        foo(); 
    }; 
    script.onreadystatechange = function() { 
        if (script.readyState === "loaded") { 
        display("Script loaded (notificaton via readyState). Calling foo just to prove it's loaded, but in the question we wouldn't know about the symbol do we wouldn't be able to call it."); 
        foo(); 
        } 
    }; 
    document.body.appendChild(script); 
    script.src = url; 
    

    這通過在Chrome 10,Firefox 3.6以上,Safari 5的,和移動Safari瀏覽器的load事件工作;通過IE6,IE7和IE8中的readystatechange事件;並通過這兩個事件在Opera 11和IE9。

+0

我不知道插入腳本的任何內容,也不希望它的作者實現任何指定的回調。沒有辦法檢測腳本何時被解析,除此之外? – Tower 2011-04-16 19:52:10

+0

@rFactor:所以你加載了一個腳本,你不知道*什麼*關於?你不知道它定義的任何全局符號? (例如,上面的選項#2)。當它被加載時,你將如何處理它呢?無論如何,在這種情況下,我已經添加了選項#3。事實證明,在'load'和'readystatechange'之間,你可以從任何需要支持的瀏覽器中獲得完整的通知。 – 2011-04-16 20:37:45

1

這取決於一個你想要在你的腳本

這裏做的是在腳本注入前的DOM已準備就緒,調用回調函數的例子。

var callback = function() { console.log('hi you called'); }; 

document.write('<script type="text/javascript" charset="utf-8">// code\n callback();<\/script>'); 

如果腳本需要使用dom,那麼它需要等待,直到它準備好了,否則不需要。

但是您的解決方案需要在您希望支持的所有瀏覽器中進行測試,因爲腳本評估和執行 的順序在IE和FF中有所不同。