Gibt es einen Grund, eine synchrone XMLHttpRequest zu verwenden?

87

Es scheint, dass fast jeder asynchrone Anforderungen mit XMLHttpRequest ausführt, aber offensichtlich zeigt die Tatsache, dass es die Möglichkeit gibt, synchrone Anforderungen auszuführen, dass es einen gültigen Grund dafür gibt. Was könnte dieser gültige Grund sein?

Darrell Brogdon
quelle
1
Das ist eine ziemlich gute Frage! Ich denke nicht, dass die Antwort sehr interessant sein wird, aber trotzdem eine großartige Frage. Haben Sie einen synchronen Anruf versucht, um zu sehen, was passieren wird?
Tad Donaghe
3
Synchrone Anrufe blockieren den Browser, was zu einer schrecklichen Benutzererfahrung führt. Also meine Frage. Ich konnte mir keinen guten Grund vorstellen, es zu benutzen.
Darrell Brogdon
2
Halbschwere Antwort: Vielleicht einfach, um das Kapitel zu füllen, das vor den asynchronen Anforderungen in dem von Ihnen gelesenen JavaScript-Buch steht.
Ben James
Persönlich möchte ich einen synchronen Ajax verwenden, um mehrere Aufrufe an serverseitige Funktionen zu verpacken, ohne für jeden Anruf eine Anforderung schreiben zu müssen.
Paul Ishak
Lokales Ausführen von Code, insbesondere für interne Entwicklungsframeworks und -tools.
user2800679

Antworten:

25

Ich denke, sie könnten mit fortschreitenden HTML 5-Standards populärer werden. Wenn eine Webanwendung Zugriff auf Web-Worker erhält, könnte ich davon ausgehen, dass Entwickler einen dedizierten Web-Worker verwenden, um synchrone Anforderungen zu stellen, um sicherzustellen, dass eine Anforderung vor der anderen erfolgt, wie Jonathan sagte. In der aktuellen Situation eines Threads ist dies ein weniger als ideales Design, da es blockiert, bis die Anforderung abgeschlossen ist.

DC
quelle
16
Ich nehme an, er meinte "Web Workers"
Evilpie
Ich denke der destillierte Punkt. Erstellen Sie in UI-Thread einen Thread oder eine Art asynchrone Aufgabe. Wenn bereits im Thread, verwenden Sie in den meisten Fällen synchronisiert. Threads sind viel "blockfreundlicher"
HaMMeReD
Dies ist eine alte Antwort, aber dieser Kommentar gilt bereits damals, noch vor HTML5, für Browser, die 2 Threads für Anfragen bereitstellten. Ich habe ein Verbindungspool-Skript geschrieben, um beide zu verwenden, da Sie selbst bei einer asynchronen Anforderung mit einer Verbindung den Browser binden können. Wenn Sie beide verwenden, können mehr Daten durch die Leitung geschoben / gezogen werden. Aber ich denke, die Synchronisierungsanforderungen haben den Browser immer noch gebunden.
Vol7ron
Firefox (und wahrscheinlich alle Nicht-IE-Browser) unterstützt kein asynchrones XHR timeOut. HTML5-WebWorker unterstützen Zeitüberschreitungen. Daher möchten Sie möglicherweise die Synchronisierungs-XHR-Anforderung mit Zeitüberschreitung an WebWorker umschließen, um asynchrones XHR mit Zeitüberschreitungsverhalten zu implementieren.
Dmitry Kaigorodov
1
-1. Dies ist keine große Antwort und die ganze Diskussion über Threads verwirrt die Sache nur. Die Antwort von Sami unten ist tatsächlich viel besser.
Stijn de Witt
30

Synchrone XHRs sind nützlich zum Speichern von Benutzerdaten. Wenn Sie das beforeunloadEreignis behandeln, können Sie Daten auf den Server hochladen, während der Benutzer die Seite schließt.

Wenn dies mit der asynchronen Option durchgeführt würde, könnte die Seite geschlossen werden, bevor die Anforderung abgeschlossen ist. Wenn Sie dies synchron tun, wird sichergestellt, dass die Anforderung in der erwarteten Weise abgeschlossen wird oder fehlschlägt.

Sami Samhuri
quelle
4
Bearbeitet: Mir ist klar, dass Sie nur txt von einem faulen HN-Benutzer ausgeben, aber ein wenig Zeit, um es gut zu formulieren, wird hier auf SO geschätzt.
Frank Krueger
Aber eigentlich ist dies der einzig gültige Grund, den ich bisher gesehen habe.
Stijn de Witt
@Frank Krueger Was ist HN?
Douglas Held
1
@DouglasHeld Eine Website namens Hacker News unter news.ycombinator.com
Sami Samhuri
13

Aktualisieren:

Das Folgende deutete darauf hin, dass es mit dem Aufkommen einer besseren asynchronen Anforderungsbearbeitung wirklich keinen Grund gibt, synchrone Anforderungen zu verwenden, es sei denn, die Absicht, die Benutzer absichtlich daran zu hindern, etwas zu tun, bis eine Anforderung abgeschlossen ist, klingt bösartig: )

Obwohl dies schlecht klingt, kann es Zeiten geben, in denen es wichtig ist, dass eine Anforderung (oder eine Reihe von Anforderungen) auftritt, bevor ein Benutzer eine Seite verlässt oder bevor eine Aktion ausgeführt wird - das Blockieren der Ausführung anderer Codes (z. B. das Verhindern der Zurück-Schaltfläche) könnte dies tun möglicherweise Fehler / Wartung für ein schlecht entworfenes System reduzieren ; Das heißt, ich habe es noch nie in freier Wildbahn gesehen und betont, dass es vermieden werden sollte.

Bibliotheken täuschen wie Versprechen Synchronizität vor, indem sie Prozesse über Rückrufe verketten. Dies entspricht den meisten Entwicklungsanforderungen, bei denen der Wunsch besteht, nicht blockierende Ereignisse zu bestellen, die es den Browsern ermöglichen, die Reaktionsfähigkeit für den Benutzer beizubehalten (gute UX).

Wie in den Mozilla-Dokumenten angegeben, gibt es Fälle, in denen Sie synchrone Anforderungen verwenden müssen. Es wird jedoch auch eine Problemumgehung aufgeführt, bei der Beacon (in IE / Safari nicht verfügbar) für solche Fälle verwendet wird. Während dies experimentell ist, könnte es, falls es jemals die Akzeptanz von Standards erreicht, möglicherweise einen Nagel in den Sarg für synchrone Anfragen stecken.


Sie möchten synchrone Aufrufe in jeder Art von transaktionsähnlicher Verarbeitung ausführen oder überall dort, wo eine Betriebsreihenfolge erforderlich ist.

Angenommen, Sie möchten ein Ereignis anpassen, um sich nach dem Abspielen eines Songs abzumelden. Wenn der Abmeldevorgang zuerst ausgeführt wird, wird das Lied niemals abgespielt. Dies erfordert die Synchronisierung der Anforderungen.

Ein weiterer Grund wäre die Arbeit mit einem WebService, insbesondere wenn Sie auf dem Server rechnen.

Beispiel: Der Server hat eine Variable mit dem Wert 1.

 Step (1) Perform Update: add 1 to variable
 Step (2) Perform Update: set variable to the power of 3
 End Value: variable equals 8

Wenn Schritt (2) zuerst auftritt, ist der Endwert 2, nicht 8; Daher ist die Reihenfolge der Bedienung und die Synchronisation erforderlich.


Es gibt sehr wenige Fälle, in denen ein synchroner Anruf in einem allgemeinen Beispiel der realen Welt gerechtfertigt sein kann. Möglicherweise, wenn Sie auf Anmelden und dann auf einen Teil der Site klicken, für den ein Benutzer angemeldet sein muss.

Wie andere gesagt haben, wird es Ihren Browser binden, also halten Sie sich von ihm fern, wo Sie können.

Anstelle von synchronen Aufrufen möchten Benutzer jedoch häufig ein Ereignis stoppen, das gerade geladen wird, und dann einen anderen Vorgang ausführen. In gewisser Weise ist dies eine Synchronisation, da das erste Ereignis beendet wird, bevor das zweite beginnt. Verwenden Sie dazu die abort () -Methode für das XML-Verbindungsobjekt.

vol7ron
quelle
1
Ich denke, dies sollte die wahre Antwort sein
3
@Zack: Das ist ein gutes Beispiel, aber Sie könnten wahrscheinlich dasselbe mit asynchronen Aufrufen tun, abhängig von dem Ereignis, das es aufruft.
Vol7ron
3
+1 Es gibt einen gültigen Fall, dass logische Race-Bedingungen aus asynchronen Serveranforderungen resultieren können ... Die Lösung muss jedoch nicht synchron sein. Sofern Ihre Anforderungen nicht von einem Web Worker verarbeitet werden, ist es besser, eine Transportschicht zu schreiben, die die Anforderungen nummeriert und dann sicherstellt, dass die Vorgänge in der Reihenfolge der Anforderungs-IDs ausgeführt werden.
Roy Tinker
3
-1 Die Transaktionsverarbeitung ist ein perfektes Beispiel, bei dem Sie Garantien verwenden müssen, dass Daten fehlschlagen oder erfolgreich sind. Nur weil der Befehl synchron ist, bedeutet dies nicht, dass die erste Anforderung erfolgreich war. Sie haben sich auf die Antwort verlassen, die Ihnen dies mitteilt. In diesem Beispiel würden Sie die zweite Anforderung nur innerhalb des Ergebnis-Handlers der ersten Anforderung ausführen. In diesem Fall könnten beide genauso gut asynchron sein.
Mathew
2
@Mathew: Das ist nur wahr, wenn Ihr transaktionsähnlicher Prozess vom Ergebnis der vorherigen Aktion abhängt. Wenn Sie eine Schaltfläche auf Ihrer Seite haben, mit der ein neues Objekt (vom Server abgerufen) erstellt wird; Wenn es asynchron wäre, könnte der Benutzer möglicherweise mehrmals klicken und viele Objekte zurückgeben. Ein synchroner Aufruf würde dies verhindern und erst nach Abschluss des ersten Objekts ein weiteres neues Objekt erstellen, unabhängig davon, ob es fehlerhaft ist oder nicht. Bitte achten Sie auf den Wortlaut, ich habe ihn transaktionsartig und nicht absichtlich getätigt .
Vol7ron
8

Ich würde sagen, wenn Sie erwägen, den Browser des Benutzers zu blockieren, während die Anforderung akzeptabel abgeschlossen ist, verwenden Sie auf jeden Fall eine synchrone Anforderung.

Wenn die Serialisierung von Anforderungen Ihr Ziel ist, kann dies mithilfe von asynchronen Anforderungen erreicht werden, indem der onComplete-Rückruf Ihrer vorherigen Anforderung die nächste Zeile auslöst.

Hobodave
quelle
1
Hmm, ich würde dem ein Schiebefenster hinzufügen, sonst verlieren Sie im Grunde die Hin- und Rückflugzeit für jede Anfrage
Stephan Eggermont
7

Es gibt viele reale Fälle, in denen das Blockieren der Benutzeroberfläche genau das gewünschte Verhalten ist.

Nehmen Sie eine App mit mehreren Feldern und einige Felder müssen durch einen xmlhttp-Aufruf an einen Remote-Server überprüft werden, der als Eingabe den Wert dieses Felds und andere Feldwerte bereitstellt.

Im synchronen Modus ist die Logik einfach, die Blockierung durch den Benutzer ist sehr kurz und es gibt kein Problem.

Im asynchronen Modus kann der Benutzer die Werte anderer Felder ändern, während das erste validiert wird. Diese Änderungen lösen andere xmlhttp-Aufrufe mit Werten aus dem Anfangsfeld aus, die noch nicht überprüft wurden. Was passiert, wenn die Erstvalidierung fehlgeschlagen ist? Pures Durcheinander. Wenn der Synchronisierungsmodus veraltet und verboten ist, wird die Anwendungslogik zu einem Albtraum. Grundsätzlich muss die Anwendung neu geschrieben werden, um Sperren zu verwalten (z. B. andere Elemente während des Validierungsprozesses deaktivieren). Die Komplexität des Codes nimmt enorm zu. Andernfalls kann es zu einem Logikfehler und letztendlich zu einer Beschädigung der Daten kommen.

Grundsätzlich stellt sich die Frage: Was ist wichtiger, nicht blockierte Benutzeroberflächenerfahrung oder das Risiko einer Datenkorruption? Die Antwort sollte beim Anwendungsentwickler bleiben, nicht beim W3C.

Alexandre Avrane
quelle
1
Ich denke, Sie verbinden die Idee, Benutzerinteraktionen zu blockieren, mit dem Blockieren des Browser-Threads. Es gibt eine Milliarde einfacher Möglichkeiten, um zu verhindern, dass der Benutzer während eines asynchronen Aufrufs weiterhin mit einer bestimmten Entität (Formularfeld usw.) interagiert, ohne dass der Browser-Thread blockiert werden müsste. Wenn der Thread blockiert, kann es überhaupt keine logische Verarbeitung geben, und das ist nur eine schlechte Situation. Es entstehen weit mehr Probleme / potenzielle Probleme, die praktisch unlösbar sind, als es löst.
Luke Chavers
6

Ich kann eine Verwendung für synchrone XHR-Anforderungen sehen, die verwendet werden sollen, wenn eine Ressource an einem variablen Speicherort vor anderen statischen Ressourcen auf der Seite geladen werden muss, die von der ersten Ressource abhängen, die vollständig funktioniert. Tatsächlich implementiere ich eine solche XHR-Anforderung in einem eigenen kleinen Teilprojekt, während sich JavaScript-Ressourcen abhängig von einer Reihe spezifischer Parameter an variablen Speicherorten auf dem Server befinden. Nachfolgende JavaScript-Ressourcen basieren auf diesen variablen Ressourcen, und es muss garantiert werden, dass solche Dateien geladen werden, bevor die anderen abhängigen Dateien geladen werden, wodurch die Anwendung vollständig wird.

Diese Ideengrundlage erweitert die Antwort von vol7ron wirklich. Transaktionsbasierte Prozeduren sind wirklich die einzige Zeit, in der synchrone Anforderungen gestellt werden sollten. In den meisten anderen Fällen sind asynchrone Aufrufe die bessere Alternative, bei der das DOM nach dem Aufruf nach Bedarf aktualisiert wird. In vielen Fällen, z. B. bei benutzerbasierten Systemen, können bestimmte Funktionen für "nicht autorisierte Benutzer" gesperrt sein, bis sie sich per se angemeldet haben. Diese Funktionen werden nach dem asynchronen Aufruf über ein DOM-Aktualisierungsverfahren entsperrt.

Abschließend muss ich sagen, dass ich den Punkten der meisten Personen in dieser Angelegenheit zustimme: Wo immer möglich, sollten synchrone XHR-Anforderungen vermieden werden, da der Browser bei seiner Funktionsweise mit synchronen Anrufen blockiert. Wenn Sie synchrone Anforderungen implementieren, sollten diese so ausgeführt werden, dass der Browser normalerweise ohnehin gesperrt ist, z. B. im Abschnitt HEAD, bevor die Seite tatsächlich geladen wird.

hyponiq
quelle
Die Tatsache, dass eine Aktion auf dem Ergebnis einer anderen Aktion beruht, ist kein Grund, diese andere Aktion synchron auszuführen. Nur wenn das Ergebnis einer Aktion verarbeitet werden muss, bevor die aufrufende Funktion beendet wird, benötigen Sie einen synchronen Aufruf.
Stijn de Witt
5

Ab 2015 werden Desktop-Javascript-Apps immer beliebter. Normalerweise ist in diesen Apps beim Laden lokaler Dateien (und das Laden mit XHR ist eine absolut gültige Option) die Ladegeschwindigkeit so hoch, dass es wenig Sinn macht, den Code mit Async zu komplizieren. Natürlich kann es Fälle geben, in denen Async der richtige Weg ist (Anfordern von Inhalten aus dem Internet, Laden wirklich großer Dateien oder einer großen Anzahl von Dateien in einem einzigen Stapel), aber ansonsten funktioniert die Synchronisierung einwandfrei (und ist viel einfacher zu verwenden). .

jahu
quelle
Dies ist tatsächlich die Situation, in der ich mich befinde, und es ist 2020. Ich habe eine Desktop-App, deren Benutzeroberfläche über HTTP angezeigt wird, sodass Sie über einen Browser auf dem lokalen Computer oder sogar über das Netzwerk darauf zugreifen können. In diesen Szenarien ist das Netzwerk schnell und zuverlässig, sodass synchrone XHR-Anforderungen eine gute Möglichkeit sind, den Code einfach zu halten. Die meisten Leute wissen nicht, dass asynchrone XHR-Anforderungen der Verwendung von Threads ähneln und dass dies mit vielen Möglichkeiten für Fehler sehr kompliziert werden kann.
Eric Mutta
4

jQuery verwendet unter bestimmten Umständen intern synchrones AJAX. Wenn Sie HTML einfügen, das Skripte enthält, führt der Browser diese nicht aus. Die Skripte müssen manuell ausgeführt werden. Diese Skripte können Klick-Handler anhängen. Angenommen, ein Benutzer klickt auf ein Element, bevor der Handler angehängt wird, und die Seite würde nicht wie beabsichtigt funktionieren. Um Rennbedingungen zu vermeiden, wird daher synchrones AJAX verwendet, um diese Skripte abzurufen. Da synchrones AJAX effektiv alles andere blockiert, kann sichergestellt werden, dass Skripte und Ereignisse in der richtigen Reihenfolge ausgeführt werden.

Henry Chan
quelle
2

Was passiert, wenn Sie im Produktionscode einen synchronen Aufruf tätigen?

Der Himmel fällt herunter.

Nein im Ernst, der Benutzer mag keinen gesperrten Browser.

martinr
quelle
2
Die Frage ist "warum es mit XMLHTTPREQUEST machen" nicht "warum Synchronisierungsaufrufe machen oder nicht"
Itay Moav -Malimovka
1
Wenn Sie eine angemessene Zeitüberschreitung hinzufügen, sollte dies kein Problem sein.
Greg
1
Er fragt nach Anwendungsfällen für Synchronisierungsanrufe ... Nicht wegen der Nachteile (wir alle kennen diese inzwischen ...)
Stijn de Witt
Welcher Benutzer? Sind alle Benutzer gleich? Wie wäre es mit Ingenieuren, die vor Ort testen? ... also mit sehr geringer Verzögerung auf Dateien des Dateisystems zugreifen ????
user2800679
2

Ich benutze es, um einen Benutzernamen zu validieren, während ich überprüfe, ob der Benutzername noch nicht existiert.

Ich weiß, dass es besser wäre, dies asynchron zu tun, aber dann sollte ich einen anderen Code für diese bestimmte Validierungsregel verwenden. Ich erkläre es besser. Mein Validierungssetup verwendet einige Validierungsfunktionen, die je nach Gültigkeit der Daten true oder false zurückgeben.

Da die Funktion zurückkehren muss, kann ich keine asynchronen Techniken verwenden, also mache ich das einfach synchron und hoffe, dass der Server schnell genug antwortet, um nicht zu auffällig zu sein. Wenn ich einen AJAX-Rückruf verwenden würde, müsste ich den Rest der Ausführung anders als die anderen Validierungsmethoden behandeln.

Andrea
quelle
Ein Trick in einem solchen Szenario besteht darin, dass die Validierungsfunktion nur ein Flag überprüft (das als beginnt false) und es auf true oder false setzt, wenn der Server antwortet. Beim Ändern des Feldes setzen Sie das Flag zurück und rufen den Server erneut an.
Stijn de Witt
2

Manchmal haben Sie eine Aktion, die von anderen abhängt. Beispielsweise kann Aktion B nur gestartet werden, wenn A beendet ist. Der synchrone Ansatz wird normalerweise verwendet, um Rennbedingungen zu vermeiden . Manchmal ist die Verwendung eines synchronen Aufrufs eine einfachere Implementierung als die Erstellung einer komplexen Logik, um jeden Zustand Ihrer asynchronen Aufrufe zu überprüfen, der voneinander abhängt.

Das Problem bei diesem Ansatz besteht darin, dass Sie den Browser des Benutzers "blockieren", bis die Aktion abgeschlossen ist (bis die Anforderung zurückgegeben, beendet, geladen usw. wird). Seien Sie also vorsichtig, wenn Sie es verwenden.

GmonC
quelle
Die Frage ist "warum es mit XMLHTTPREQUEST tun" nicht "warum Anrufe synchronisieren"
Itay Moav -Malimovka
Der Autor selbst sagt: " Synchrone Anrufe blockieren den Browser, was zu einer schrecklichen Benutzererfahrung führt." In einem Kommentar haben sich also alle in diesem Thread für den Ansatz "Synchrone Anrufe" beworben. Warum haben Sie dieses wörtliche Verständnis der Frage angenommen, wenn Sie nicht genau sagen können, was der Autor gemeint hat?
GmonC
2

Ich verwende synchrone Aufrufe bei der Entwicklung von Code. Was auch immer Sie getan haben, während die Anforderung zum und vom Server pendelte, kann die Fehlerursache verschleiern.

Wenn es funktioniert, mache ich es asynchron, aber ich versuche, einen Abbruch-Timer und Fehler-Rückrufe einzuschließen, weil Sie nie wissen ...

kennebec
quelle
2

Grund:

Angenommen, Sie haben eine Ajax-Anwendung, die ein halbes Dutzend http ausführen muss, um verschiedene Daten vom Server zu laden, bevor der Benutzer eine Interaktion ausführen kann.

Offensichtlich möchten Sie, dass dies durch Onload ausgelöst wird.

Synchrone Aufrufe funktionieren hierfür sehr gut, ohne dass der Code komplexer wird. Es ist einfach und unkompliziert.

Nachteil:

Der einzige Nachteil ist, dass Ihr Browser abstürzt, bis alle Daten geladen sind oder eine Zeitüberschreitung auftritt. Die betreffende Ajax-Anwendung ist kein großes Problem, da die Anwendung erst dann von Nutzen ist, wenn alle anfänglichen Daten geladen sind.

Alternative?

Viele Browser sperren jedoch alle Fenster / Registerkarten, wenn das Javascript in einem von ihnen ausgelastet ist, was ein dummes Problem beim Browserdesign darstellt. Infolgedessen ist das Blockieren in möglicherweise langsamen Netzwerken nicht höflich, wenn Benutzer keine anderen Registerkarten verwenden während Sie darauf warten, dass die Ajax-Seite geladen wird.

Es sieht jedoch so aus, als ob synchrone Abrufe ohnehin aus den letzten Browsern entfernt oder eingeschränkt wurden. Ich bin mir nicht sicher, ob das daran liegt, dass jemand entschieden hat, dass sie einfach immer schlecht sind, oder ob Browser-Autoren durch den WC-Arbeitsentwurf zu diesem Thema verwirrt waren.

http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#the-open-method lässt es so aussehen (siehe Abschnitt 4.7.3), dass Sie im Blockierungsmodus kein Timeout festlegen dürfen . Scheint mir kontraintuitiv zu sein: Wenn jemand E / A blockiert, ist es höflich, ein angemessenes Zeitlimit festzulegen. Warum also das Blockieren von E / A zulassen, jedoch nicht mit einem benutzerdefinierten Zeitlimit?

Meiner Meinung nach spielt das Blockieren von E / A in einigen Situationen eine wichtige Rolle, muss aber korrekt implementiert werden. Es ist zwar nicht akzeptabel, dass eine Browser-Registerkarte oder ein Browser-Fenster alle anderen Registerkarten oder Fenster blockiert, dies ist jedoch ein Fehler im Browser-Design. Schande, wo Schande gebührt. In einigen Fällen ist es jedoch durchaus akzeptabel, dass ein einzelner Tab oder ein Fenster in einigen Situationen einige Sekunden lang nicht reagiert (z. B. durch Blockieren von IO / HTTP GET), z. B. beim Laden von Seiten, möglicherweise bei vielen Daten muss sein, bevor irgendetwas getan werden kann. Manchmal ist richtig implementierter Blockierungscode der sauberste Weg, dies zu tun.

Natürlich kann in diesem Fall eine äquivalente Funktion mit asynchronen http-Gets erhalten werden, aber welche Art von doofer Routine ist erforderlich?

Ich denke, ich würde etwas in diese Richtung versuchen:

Gehen Sie beim Laden des Dokuments wie folgt vor: 1: Richten Sie 6 globale "Done" -Flag-Variablen ein, die auf 0 initialisiert sind. 2: Führen Sie alle 6 Hintergrundabrufe aus (vorausgesetzt, die Reihenfolge spielt keine Rolle).

Dann würden die Abschlussrückrufe für jedes der 6 http-Get's ihre jeweiligen "Done" -Flaggen setzen. Außerdem würde jeder Rückruf alle anderen erledigten Flags überprüfen, um festzustellen, ob alle 6 HTTP-Abschlüsse abgeschlossen wurden. Der letzte zu vervollständigende Rückruf, der sah, dass alle anderen abgeschlossen waren, rief dann die REAL-Init-Funktion auf, die dann alles einrichtete, nachdem alle Daten abgerufen worden waren.

Wenn die Reihenfolge des Abrufs von Bedeutung ist oder wenn der Webserver nicht in der Lage ist, mehrere Anforderungen gleichzeitig zu akzeptieren, benötigen Sie Folgendes:

In onload () wird der erste http get gestartet. In seinem Rückruf würde der zweite gestartet. In seinem Rückruf der dritte - und so weiter und so fort, wobei jeder Rückruf das nächste HTTP-GET startet. Wenn der letzte zurückkehrte, rief er die echte init () - Routine auf.

Jesse Gordon
quelle
2

SYNC vs ASYNC: Was ist der Unterschied?

Im Grunde läuft es darauf hinaus:

console.info('Hello, World!');
doSomething(function handleResult(result) {
    console.info('Got result!');
});
console.info('Goodbye cruel world!');

Wenn dies synchrondoSomething ist, wird Folgendes gedruckt:

Hello, World!
Got result!
Goodbye cruel world!

Wenn dies dagegen asynchron ist , doSomethingwird Folgendes gedruckt:

Hello, World!
Goodbye cruel world!
Got result!

Da die Funktion doSomethingihre Arbeit asynchron ausführt, kehrt sie zurück, bevor ihre Arbeit erledigt ist. Das Ergebnis erhalten wir also erst nach dem DruckenGoodbye cruel world!

Wenn wir vom Ergebnis eines asynchronen Aufrufs abhängig sind, müssen wir den abhängigen Code in den Rückruf einfügen:

console.info('Hello, World!');
doSomething(function handleResult(result) {
    console.info('Got result!');
    if (result === 'good') {
        console.info('I feel great!');
    }
    else {
        console.info('Goodbye cruel world!');
    }
});

Daher ist nur die Tatsache, dass zwei oder drei Dinge in der Reihenfolge geschehen müssen, kein Grund, sie synchron auszuführen (obwohl der Synchronisierungscode für die meisten Menschen einfacher zu handhaben ist).

WARUM SYNCHRONE XMLHTTPREQUEST VERWENDEN?

In einigen Situationen benötigen Sie das Ergebnis, bevor die aufgerufene Funktion abgeschlossen ist. Stellen Sie sich dieses Szenario vor:

function lives(name) {
    return (name !== 'Elvis');
}
console.info('Elvis ' + (lives('Elvis') ? 'lives!' : 'has left the building...');

Angenommen, wir haben keine Kontrolle über den aufrufenden Code (die console.infoLeitung) und müssen die Funktion ändern lives, um den Server zu fragen ... Wir können auf keinen Fall eine asynchrone Anforderung an den Server von innen ausführen livesund haben unsere Antwort noch vor livesAbschluss. Wir würden also nicht wissen, ob wir zurückkehren sollen trueoder nicht false. Die einzige Möglichkeit, das Ergebnis vor Abschluss der Funktion zu erhalten, besteht in einer synchronen Anforderung.

Wie Sami Samhuriin seiner Antwort erwähnt, ist das onbeforeunloadEreignis ein sehr reales Szenario, in dem Sie möglicherweise eine Antwort auf Ihre Serveranforderung benötigen, bevor Ihre Funktion beendet wird , da es die letzte Funktion Ihrer App ist, die jemals ausgeführt wird, bevor das Fenster geschlossen wird.

ICH BRAUCHE KEINE SYNCH CALLS, ABER ICH BENUTZE SIE JEDERZEIT, WIE SIE EINFACHER SIND

Bitte nicht. Synchrone Anrufe sperren Ihren Browser und sorgen dafür, dass die App nicht mehr reagiert. Aber Sie haben Recht. Async-Code ist schwieriger. Es gibt jedoch eine Möglichkeit, den Umgang damit viel einfacher zu gestalten. Nicht so einfach wie Synchronisierungscode, aber es kommt näher: Versprechen s.

Hier ein Beispiel: Zwei asynchrone Aufrufe sollten beide erfolgreich abgeschlossen werden, bevor ein drittes Codesegment ausgeführt werden kann:

var carRented = rentCar().then(function(car){
  gasStation.refuel(car);
});

var hotelBooked = bookHotel().then(function(reservation) {
  reservation.confirm();
});

Promise.all([carRented, hotelBooked]).then(function(){
  // At this point our car is rented and our hotel booked.
  goOnHoliday();
});

So würden Sie implementieren bookHotel:

function bookHotel() {
  return new Promise(function(resolve, reject){
    if (roomsAvailable()) {
      var reservation = reserveRoom();
      resolve(reservation);
    }
    else {
      reject(new Error('Could not book a reservation. No rooms available.'));
    }
  });
}

Siehe auch: Besseres JavaScript mit Versprechen schreiben .

Stijn de Witt
quelle
1
"Bitte nicht. Synchrone Anrufe sperren Ihren Browser und sorgen dafür, dass die App nicht mehr reagiert." Dies ist nicht immer ein Problem. Stellen Sie sich vor, Sie testen localhost und sind ein Entwickler.
user2800679
2

XMLHttpRequestwird traditionell für asynchrone Anforderungen verwendet. Manchmal (zum Debuggen oder für eine bestimmte Geschäftslogik) möchten Sie alle / mehrere asynchrone Aufrufe auf einer Seite für die Synchronisierung ändern.

Sie möchten dies tun, ohne alles in Ihrem JS-Code zu ändern. Das Async / Sync-Flag bietet Ihnen diese Möglichkeit. Bei korrekter Gestaltung müssen Sie nur eine Zeile in Ihrem Code ändern / den Wert von 1 varwährend der Ausführungszeit ändern .

Itay Moav-Malimovka
quelle
1

Firefox (und wahrscheinlich alle Nicht-IE-Browser) unterstützt kein asynchrones XHR timeOut.

  1. Stackoverflow-Diskussion
  2. Mozilla Firefox XMLHttpRequest

HTML5- WebWorker unterstützen Zeitüberschreitungen. Daher möchten Sie möglicherweise die Synchronisierungs-XHR-Anforderung mit Zeitüberschreitung an WebWorker umschließen, um asynchrones XHR mit Zeitüberschreitungsverhalten zu implementieren.

Dmitry Kaigorodov
quelle
1

Ich hatte gerade eine Situation, in der asynchrone Anforderungen für eine Liste von URLs, die nacheinander mit forEach (und einer for-Schleife) aufgerufen wurden, dazu führten, dass die verbleibenden Anforderungen abgebrochen wurden. Ich habe auf synchron umgestellt und sie funktionieren wie vorgesehen.

AD Regan
quelle
1

Die Verwendung synchroner HTTP-Anforderungen ist im Geschäft mit mobiler Werbung eine gängige Praxis.

Unternehmen (auch bekannt als "Publisher"), die Anwendungen erstellen, schalten häufig Anzeigen, um Einnahmen zu erzielen. Dazu installieren sie Werbe-SDKs in ihrer App. Viele existieren (MoPub, Ogury, TapJob, AppNext, Google Ads AdMob).

Diese SDKs liefern Anzeigen in einer Webansicht.

Wenn Sie eine Anzeige für einen Nutzer schalten , muss dies eine reibungslose Erfahrung sein, insbesondere beim Abspielen eines Videos. Es sollte zu keinem Zeitpunkt gepuffert oder geladen werden.

Um dies zu lösen, precachingwird verwendet. Wo die Medien (Bild / Videos / usw.) synchron im Hintergrund der Webansicht geladen werden.

Warum nicht asynchron?

  1. Dies ist Teil eines weltweit anerkannten Standards
  2. Das SDK wartet darauf, dass das onloadEreignis weiß, wann die Anzeige "bereit" ist, um dem Nutzer geliefert zu werden

Mit der Ablehnung synchroner XMLHttpRequests wird das Anzeigengeschäft höchstwahrscheinlich gezwungen sein, den Standard in Zukunft zu ändern, sofern kein anderer Weg festgelegt werden kann.

kemicofa Geist
quelle
0

Synchrones XHR kann für die Entwicklung interner Tools und / oder Frameworks (ohne Produktion) sehr nützlich sein. Stellen Sie sich zum Beispiel vor, Sie möchten beim ersten Zugriff eine Codebibliothek synchron laden:

get draw() 
{
    if (!_draw)
    {
       let file;
       switch(config.option)
       {
           case 'svg':
              file = 'svgdraw.js';
              break;
           case 'canvas':
              file = 'canvasdraw.js';
              break;
           default:
              file = 'webgldraw.js';
       }

       var request = new XMLHttpRequest();
       request.open('GET', file, false);
       request.send(null);
       _draw = eval(request.responseText);
    }

    return _draw;
}

Denken Sie daran, dass dies nur für lokale Tests gedacht ist, bevor Sie sich in ein Schwindelgefühl versetzen und blind das Böse der Eval erbrechen. Für Produktions-Builds wäre _draw bereits festgelegt.

Ihr Code könnte also folgendermaßen aussehen:

foo.drawLib.draw.something(); //loaded on demand

Dies ist nur ein Beispiel für etwas, das ohne die Synchronisierung von XHR nicht möglich wäre. Sie könnten diese Bibliothek im Voraus laden, ja, oder ein Versprechen / einen Rückruf machen, aber Sie könnten die Bibliothek nicht synchron laden, ohne XHR zu synchronisieren. Überlegen Sie, wie viel diese Art von Dingen Ihren Code bereinigen könnte ...

Die Grenzen dessen, was Sie damit für Werkzeuge und Frameworks (lokal ausgeführt) tun können, sind nur durch Ihre Vorstellungskraft begrenzt. Es scheint jedoch, dass die Vorstellungskraft in der JavaScript-Welt etwas eingeschränkt ist.

user2800679
quelle
-1

Hier ist ein guter Grund. Ich wollte eine http-Anfrage machen und dann je nach Ergebnis click () für einen Eingabetyp = file aufrufen. Dies ist mit asynchronem xhr oder fetch nicht möglich. Der Rückruf verliert den Kontext "Benutzeraktion", sodass der Aufruf click () ignoriert wird. Synchrones xhr hat meinen Speck gerettet.

onclick(event){
    //here I can, but I don't want to.
    //document.getElementById("myFileInput").click();
    fetch("Validate.aspx", { method : "POST", body: formData, credentials: "include" })
    .then((response)=>response.json())
    .then(function (validResult) {
        if (validResult.success) {
            //here, I can't.
            document.getElementById("myFileInput").click();
        }
    });
}
bbsimonbb
quelle
Speichern Sie es auf einem var
Es Noguera