2016-07-16 91 views
1

在我的用例中,我使用外部和內聯JavaScript內容。我有以下結構。如何延遲內聯javascript加載時間?

app/ 
     header.html 
     home.html 
     config-load.js 
     footer.html 

home.html包括header.htmlfooter.htmlheader.html文件包括config-load.js

config-load.js一個Ajax調用來獲取基於來自golang後端舞臺CONFIGS。這可能有幾毫秒的延遲。

home.html中很少有內聯腳本,它使用由config-load.js ajax調用收集的配置。

所以加載內嵌腳本之前config-load.js Ajax調用必須完成。但它正在以另一種方式加載。

我試着用while循環延遲加載時間,如下內嵌腳本,

while(configReceived == false) 
{ 
    setTimeout(function(){ 
    console.log("waiting for config"); 
    }, 2000); 
} 
if(configReceived) 
{ 
    //process configs 
} 

但這阻止該線程。該頁面停留在while循環中。有沒有其他方法可以實現這一點?

編輯1: 這裏是內嵌腳本內容,

<script type="text/javascript"> 
    window.onload = function() { 
     time = new Date($.now()); 
     var tagsArray = ["C", "C++", "Go", "Ruby"]; 
     //var tagsArray = []; 
     requestJSON = '{"Method":"GET","AppName":"Web-app","ServiceURL":"'+endpoints.Tags.HTTPEndpoint.URL+'","Properties":null,"Object":"","Timestamp":"'+time+'"}' 
     $.ajax({ 
     type: "GET", 
     url: endpoints.Tags.HTTPEndpoint.URL, 
     data: requestJSON, 
     processData: false, 
     contentType: "application/json;", 
     dataType: "json", 
     async: false, 
     success: function(data){ 
      console.log("tags retrieved successfully info updated successfully") 
      console.log("Tags ", data.Object) 
      tagsArray = data.Object 
     }, 
     failure: function(errMsg) { 
      console.log("Error occured in getting tags ", errMsg) 
     } 
     }); 
     $("#myTags").tagit(); 
     $("#tags").tagit({ 
     fieldName: "tagsName", // The name of the hidden input field 
     availableTags: tagsArray, 
     allowSpaces:true, 
     caseSensitive:false, 
     removeConfirmation:true, 
     placeholderText:"Tags", 
     tagLimit: 5, 
     allowDuplicates: false, 
     singleField: true, // Use a hidden input element with the fieldName name 
     singleFieldDelimiter: ',', // Optional, default value is same. 
     onlyAvailableTags: false 
     }); 
    } 
</script> 

而且我的配置,load.js看起來像下面,

////////////////////////////////////////////////////////// 
// code block to get the service endpoints by stage starts 
var xhr = new XMLHttpRequest(); 
xhr.onreadystatechange = function() { 
    if (xhr.readyState == 4 && xhr.status == 200) { 
     endpoints = JSON.parse(xhr.responseText); 
     console.log("server endpoints be ", endpoints); 
     configReceived = true; 
    } 
} 
xhr.open("GET", "/config", true); 
try { 
    xhr.send(); 
} catch (err) { 
    // handle error 
    console.log("Error occured in getting the service endpoints. This may break all ajax services"); 
} 
// code block to get the service endpoints by stage ends 
//////////////////////////////////////////////////////// 

我想最近3天,但沒有運氣。

+0

嘗試將'config-load.js'和'anotherscript.js'放入您的'footer.html' –

回答

1

要知道,JavaScript是異步的,你沒有完全控制腳本的加載順序,除非你使用的不是async await新的JavaScript功能或者promises。但你的情況並不是真的需要這些。

您需要做的第一件事就是將config-load.js包含在頂部的頂部,這樣您就可以保證文件在DOM填充前加載。

另一件事是在內聯腳本中使用window.onload函數,以在所有DOM結構已經構建並完全填充之後強制瀏覽器解析腳本。

所以HTML代碼段內包裝您的功能到window.onload回調函數:

<script type="text/javascript"> 
    window.onload = function() { 
     while(configReceived == false) 
     { 
      setTimeout(function(){ 
      console.log("waiting for config"); 
      }, 2000); 
     } 
     if(configReceived) 
     { 
      //process configs 
     } 
    } 
</script> 

編輯:

有在你的方法有不少錯誤。首先,不需要在兩個單獨的腳本中調用ajax請求。使用上面提到的承諾技術,您可以鏈接響應。這裏是jQuery的承諾是如何工作的一個簡單的例子:

function first() { 
    return $.ajax(...); 
} 

function second(data, textStatus, jqXHR) { 
    return $.ajax(...); 
} 

function third(data, textStatus, jqXHR) { 
    return $.ajax(...); 
} 

function main() { 
    first().then(second).then(third); 
} 

記住:連鎖羣中的呼叫返回響應。這意味着您可以將響應委託給下一個鏈,這意味着當請求解決後,您可以將結果傳遞給下一個呼叫。

當您通過調用端點服務接收到響應時應用於您的示例,您可以將結果作爲參數傳遞給下一個調用,並且只有在解析第一個調用的響應時纔會訪問此結果。

以此fiddle爲例。

應用此技術不再需要檢查configReceived = true;

你必須確定的另一件事是在你試圖調用jQuery.ajax之前包含了jQuery。

以下是有關承諾一些參考:

http://www.danieldemmel.me/blog/2013/03/22/an-introduction-to-jquery-deferred-slash-promise/ http://www.bitstorm.org/weblog/2012-1/Deferred_and_promise_in_jQuery.html https://davidwalsh.name/write-javascript-promises

+0

謝謝Simo。我在內嵌腳本中使用[tag-it](http://aehlke.github.io/tag-it/)。當我做窗口加載時,它會給我錯誤,如'Uncaught TypeError:$(...)。tagit不是函數'。 :(你有什麼想法 – Dany

+0

恐怕jquery沒有加載,這就是爲什麼你會得到這個錯誤 –

+0

是的當我刪除window.onload,我沒有看到這個錯誤,但順序是不同的。不知道這兩者之間有什麼關係 – Dany

1

「while循環」是同步的,這意味着它會阻塞線程,使整個應用程序卡住。

Javascript異步腳本的執行順序不能保證,所以你應該使用「回調」或在ES6中使用承諾,ES7你可以使用異步,等待。

但無論如何,更好的辦法是換你config-load.js JavaScript代碼的功能,如果你使用jQuery的AJAX API,代碼可能看起來像這樣:

function loadConfigAjax(callback){ 
    $.ajax({url: "http://myconfig", success: function(config){ 
    callback(config) 
}}); 
} 

而在你的內聯JavaScript可能看起來像這樣

<script type="text/javascript"> 
    window.onload = function() { 
     var configReceived = function(config){ 
      //process configs 
     }; 
     // pass the configReceived as callback 
     // so that configReceived function will always be invoked after config received 
     loadConfigAjax(configReceived); 
    } 
</script>