2017-03-02 1 views
0

Ich habe eine harte Zeit, selbst diese Frage zu stellen, weil ich nicht verstehe, was vor sich geht.Javascript-Methode funktioniert und funktioniert nicht

Grundsätzlich habe ich ein rotierendes Ladeelement, das angezeigt werden soll, während mein Javascript läuft. Am Ende des Javascript sollte der Loader ausgeschaltet werden und ein Modal sollte mit Daten angezeigt werden, die von einer Datenbank abgefragt wurden. Das Problem ist, dass der Loader niemals angezeigt wird. Es dauert ungefähr 1 - 2 Sekunden, bis die Abfragen ausgeführt werden, bevor das Modal erstellt wird.

function includeConnectionJS() { 
    if (!(typeof sforce === "object")) { 
     var connectionJS = document.createElement('script'); 
     var documentHead = document.getElementsByTagName('head')[0]; 

     connectionJS.src = '/soap/ajax/38.0/connection.js'; 
     connectionJS.setAttribute('onload', 'createLoader();createModal();'); 
     documentHead.appendChild(connectionJS); 
    } else { 
     createLoader(); 
     // Checks to see if the loader element exists. If it does not, create the element and than toggle it to display it. 
     // If the element already exists, display the modal 
     createModal(); 
     // Checks to see if the modal element exists, if it does not, create the element and than turn off the loader and display the modal. 
     // If the element already exists, turn off the loader and display the modal 
    } 
} 

Ich habe console.logs in meinen Methoden und ich kann deutlich sehen, dass die Methode aufgerufen wird, wird die if-Anweisungen sind alle vorbei und die Sichtbarkeit des Elements zu den richtigen Zeiten auf die richtigen Werte zu verändern. Alles deutet darauf hin, dass es funktionieren sollte, aber das Element wird nie wirklich angezeigt.

Ich war in der Lage, es zu erhalten, indem Sie den Anruf zu createModal anzuzeigen, um wie folgt aussehen: nur eine künstliche Verzögerung

setTimeout(function(){createModal()}, 100); // Most values for delay worked. 

Ich will nicht schaffen Lader Wirkung zeigen.

Meine Hauptsorge ist, dass die createModal-Methode Aufrufe an die Datenbank macht. Diese verursachen Verzögerungen in der JavaScript-Ausführung (ich nenne sie synchron, nicht asynchron). Ich kann deutlich sehen, dass die Loader-Anzeige vor den Abfragen auf "Blockieren" eingestellt ist, alle Abfragen abwarten und zurückkehren und die Anzeige des Loaders in der richtigen Reihenfolge wieder auf "none" wechseln. Mehr als das, wenn ich die createLoader() aufrufen; Methode direkt von der Konsole aus, es funktioniert.

Ich kann einfach nicht herausfinden, was ich vermisse.

+0

Alles, was Sie beschreiben, von der richtigen Reihenfolge bis 'setTimeout'" Fixing "klingt wie' createModal() 'schaltet den Loader zu früh aus. Wir können Ihnen nicht helfen, ohne den Rest Ihres Codes zu sehen. Ein Schuss im Dunkeln: Wenn Sie JS sagen wollen, A() nach B zu tun, müssen Sie 'function() {A(); } ', im Gegensatz zu' A(); '. –

+0

@ChrisG Nein, es liegt in der Natur von Javascript, Aktualisierungen der Benutzeroberfläche zu blockieren, bis der Code vollständig ausgeführt wurde. Auch Javascript wird sequentiell in einem einzelnen Thread ausgeführt, so dass 'A' immer nach' B' für 'B() ausgeführt wird; A(); '. 'A' kann niemals beginnen, bis' B' beendet ist –

Antwort

1

Mit synchronen Javascript-Aufrufen blockieren Sie die Benutzeroberfläche und andere Funktionen, die sich in der Ereignisschleife https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop#Run-to-completion befinden. Es ist wichtig daran zu denken, dass JavaScript-Code in einem einzigen Thread ausgeführt wird. So kann kein Code parallel ausgeführt werden, alles andere muss warten, bis die aktuelle Aufgabe erledigt ist. In der Praxis bedeutet dies, dass Sie möchten, dass Ihre Funktionen so schnell wie möglich ausgeführt werden, damit andere Vorgänge (UI-Updates, Tastatur-/Mausereignisse usw., Timeouts oder asynchrone Rückrufe usw.) ausgeführt werden können. Sie müssen alle warten, bis Sie die Kontrolle an die Engine übergeben, indem Sie den aktuellen Codeblock vervollständigen.

setTimeout funktioniert, weil sie für die langen Lauf createModal Funktion der Ereigniswarteschlange für die Ausführung fügt irgendwann in der Zukunft (auch wenn auf 0 ms gesetzt - es ist nicht die sofortige Ausführung garantiert sie sagt nur auf dem ersten Gelegenheit können Sie irgendwann nach 0ms hat Wenn Sie eine lange laufende Funktion haben, die möglicherweise 10 Sekunden später ist). Auf diese Weise kann die aufrufende Funktion schnell ausgeführt werden und die Benutzeroberfläche kann nun alle Aktualisierungen anwenden. Wenn die JavaScript-Engine nun bereit ist, weiteren Code auszuführen, sucht sie nach dem nächsten in der Ereignisschleife aufgezeichneten Code-Block. Dieses Mal, wenn es createModal läuft, wird es wieder Updates auf der UI usw. blockieren, Maus & Tastaturereignisse usw. übergebend, aber jetzt hat die UI die Gelegenheit gehabt, zu aktualisieren, Sie haben Ihren Spinner oben.

Also die Auswahlmöglichkeiten: entweder asynchrone Aufrufe in Ihrer Funktion verwenden, so dass es schnell abgeschlossen wird, oder wenn das nicht möglich ist weiter setTimeout() verwenden, um die lange laufende Aufgabe in Warteschlange nach der UI aktualisiert.