簡體   English   中英

Javascript:等待動態加載的腳本就緒

[英]Javascript: waiting for dynamically loaded script to be ready

我正在使用以下代碼在 html 頁面中動態加載腳本(因為在提供頁面之前我不知道 URL):

let script = document.createElement('script');
script.src = 'https://foo/bar/myscript.js';
script.async = false;
script.defer = false;
document.head.appendChild(script);

//Try to use a global function defined in the script:
myFun(); //This raises "undefined" error

按照這里的建議: https://stackoverflow.com/a/7308984/300741我將asyncdefer屬性設置為false ,以確保腳本在我嘗試使用它之前加載。 但是從最后一行代碼的注釋中可以看出,這是行不通的。

我在這里錯過了什么? 請注意,如果我在調用myFun()之前使用setTimeout()稍等片刻,它會按預期工作,所以這絕對是一個異步/延遲加載問題……但我該如何解決呢? (順便使用Chrome)

您可以在腳本onload事件上調用該函數

 let script = document.createElement('script'); script.async = false; script.defer = false; document.head.appendChild(script); script.onload = function(){ // script is loaded myFun(); } script.src = 'https://foo/bar/myscript.js';

讓我們試着了解會發生什么。 您的 Javascript 代碼嘗試從服務器加載文件。 文件加載不是一個快速的操作,特別是在運行網絡瀏覽器的客戶端計算機遠離服務器並且請求必須通過不同數量的計算機的情況下。 您的 Javascript 代碼不會等待腳本。 相反,它會繼續運行,並且腳本將在成功下載后加載。 因此,您可以使用在加載時運行的 回調,如下所示:

let script = document.createElement('script');
                script.src = 'https://foo/bar/myscript.js';
                script.async = false;
                script.defer = false;
                document.head.appendChild(script);

                script.onload = function() {
                    myFun();
                };

這將確保腳本在您的代碼之前加載,而您的代碼是在腳本加載后執行的。

您的代碼的問題是默認情況下腳本是異步加載的,即使您已將asyncdefer屬性設置為false async屬性僅適用於外部腳本(具有src屬性的腳本),它表示腳本應在下載后立即執行,而不會阻塞解析器。 defer屬性也只適用於外部腳本,它表示腳本應該在頁面解析完成后執行。

異步加載腳本時,瀏覽器不會阻塞頁面的解析,在腳本下載執行完之前,繼續執行頁面上的JavaScript的rest。 這意味着當腳本完成加載並調用 myFun() function 時,它可能尚未定義。

您可以通過使用腳本元素的onload事件來解決此問題,以便在腳本完成加載時收到通知。 加載腳本后,您可以調用myFun() function。

let script = document.createElement('script');
script.src = 'https://foo/bar/myscript.js';
script.onload = function() {
    myFun();
};
document.head.appendChild(script);

或者,如果您正在加載的腳本提供了一個全局變量或 function,您可以檢查它是否存在,您可以在調用myFun()之前使用 while 循環來檢查它是否存在

let script = document.createElement('script');
script.src = 'https://foo/bar/myscript.js';
document.head.appendChild(script);

while(!myFun){
    // wait for myFun to be defined
}
myFun();

請記住,如果腳本從未完成加載,這種方法可能會導致無限循環,因此實現超時機制很重要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM