2016-07-16 34 views
1

In meinem Anwendungsfall verwende ich sowohl externe als auch Inline-Javascript-Inhalte. Ich habe folgende Struktur.Wie verzögere ich die Inline-Javascript-Ladezeit?

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

home.html umfasst header.html und footer.html. header.html Datei enthält config-load.js.

config-load.js macht einen Ajax-Aufruf, um die Konfigurationen auf der Bühne von Golang Backend zu erhalten. Dies kann einige Millisekunden Verzögerung haben.

Es gibt einige Inline-Skripte in home.html, die die von config-load.js gesammelten Ajax-Aufrufe verwenden.

So config-load.js Ajax Aufruf muss abgeschlossen sein, bevor Inline-Skripte geladen werden. Aber es lädt in die andere Richtung.

ich versuchte, eine while-Schleife zu verwenden, wie unten die Ladezeit für die Inline-Skripte zu verzögern,

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

Aber Dies blockiert den Faden. Die Seite bleibt in der while-Schleife hängen. Gibt es einen anderen Weg, dies zu erreichen?

EDIT 1: Hier ist der Inline-Skriptinhalt,

<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> 

Und mein config-load.js wie unten aussieht,

////////////////////////////////////////////////////////// 
// 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 
//////////////////////////////////////////////////////// 

Ich versuche, für die letzten 3 Tage, aber kein Glück.

+0

Versuchen Sie 'config-load.js' und' anotherscript.js' in Ihre 'footer.html' –

Antwort

1

Seien Sie sich bewusst, dass JavaScript asynchron ist und Sie nicht die volle Kontrolle über die Lade-Sequenzen der Skripte haben, es sei denn, Sie verwenden nicht die neue JavaScript-Funktion async await oder promises. Aber in Ihrem Fall ist nicht wirklich für diese benötigt.

Als erstes müssen Sie die config-load.js in den Kopfbereich einfügen, ganz oben. So haben Sie eine Garantie, dass die Datei geladen wird, bevor das DOM gefüllt wird.

Eine andere Sache ist, die window.onload Funktion innerhalb der Inline-Skripts zu verwenden, um den Browser zu zwingen, die Skripts nur zu analysieren, nachdem die gesamte DOM-Struktur erstellt und vollständig aufgefüllt wurde.

So in Ihrem HTML-Abschnitt wickeln Sie Ihre Funktion in den window.onload Funktion Rückruf:

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

EDIT:

Es gibt durchaus ein paar Fehler in Ihrem Ansatz. In erster Linie müssen die Ajax-Anfragen nicht in zwei separaten Skripten aufgerufen werden. Mit der oben genannten Technik können Sie die Antworten verketten. Hier ist ein kurzes Beispiel, wie die jquery Versprechen arbeiten:

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); 
} 

Denken Sie daran,: ein Anruf in der Kette Gruppe die Antwort zurück.Dies bedeutet, dass Sie die Antwort an die nächste Kette delegieren können, was bedeutet, dass Sie nach der Auflösung der Anfrage das Ergebnis an den nächsten Anruf weiterleiten können.

Wenn Sie auf Ihr Beispiel zugreifen, wenn Sie die Antwort durch Aufrufen des Endpoints-Dienstes erhalten, können Sie das Ergebnis als Parameter an den nächsten Anruf weitergeben. Auf diesen wird nur zugegriffen, wenn die Antwort vom ersten Anruf aufgelöst wird.

Überprüfen Sie diese fiddle als ein Beispiel.

Mit dieser Technik wird nicht mehr benötigt, um configReceived = true; zu überprüfen.

Eine andere Sache, die Sie sicherstellen müssen, ist, dass jQuery enthalten ist, bevor Sie versuchen, jQuery.ajax aufzurufen.

Hier sind einige Referenzen über Versprechen:

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

Danke Simo. Ich verwende [tag-it] (http://aehlke.github.io/tag-it/) in einem Inline-Skript. Wenn ich das Fenster lade, gibt es einen Fehler wie 'Uncaught TypeError: $ (...). Tagit ist keine Funktion'. :(. Haben Sie eine Idee. – Dany

+0

Ich fürchte, jquery ist nicht geladen, deshalb erhalten Sie diesen Fehler. –

+0

Ja. Wenn ich window.onload entferne, sehe ich diesen Fehler nicht, aber die Reihenfolge ist anders. Ich bin nicht sicher, was die Beziehung zwischen diesen beiden ist .. – Dany

1

„while-Schleife“ synchron ist, was bedeutet, dass sie den Faden blockieren und gesamte Anwendung fest macht.

Javascript async Skripts Ausführungsreihenfolge ist nicht garantiert, so sollten Sie den "Rückruf" verwenden oder in ES6 können Sie Versprechen, ES7 können Sie async verwenden, warten.

Wie auch immer der bessere Weg wickeln ist Ihr config-load.js Javascript-Code in einer Funktion, wenn Sie jQuerys Ajax api verwenden, kann der Code sieht wie folgt aus:

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

Und in Ihrem Inline JavaScript ist möglicherweise wie folgt aussieht

<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>