Parallelität
JavaScript ist sehr auf Geschwindigkeit ausgelegt. Wegbseiten sollen möglichst schnell geladen werden, da ist keine Zeit für Bummeln.
Möchtest du etwas sehr aufwendiges berechnen, und den Nutzer trotzdem nicht warten lassen. Kannst du dies wie folgt tun:
async function f() {
// super komplexe Berechnung, die sehr lange dauert
return 1;
}
f()
.then(
console.log(f()); // 1
);
console.log(2);
Es wird zuerst die 2 und erst danach die 1 in der Konsole ausgegeben. Warum? Nun die Funktion mit dem Schlüsselwort async
wurde vereinfacht gesagt auf dem zweiten Kern des Prozessors ausgeführt, wohingegen das Hauptprogramm auf dem ersten Kern weiterlief.
Wäre es uns wichtig, auf die super komplexe Berechnung, die sehr lange dauert, zu warten, könnten wir das wie folgt erreichen:
async function a() {
async function f() {
// super komplexe Berechnung, die sehr lange dauert
return 1;
}
var keineZahl = f();
var zahl = await f();
}
a();
Die Variable keineZahl
erhält tatsächlich keinen Inhalt, da das Hauptprogramm schon vor dem Ergebnis von f()
weitergegangen ist. Bei zahl
wartet es hingegen auf das Ergebnis. Und das ist das Problem, damit müsste ja ein Browser hier warten. Da das für Anwender aber unerträglich ist, wenn der Browser nicht reagiert, darf nur in ebenfalls asynchronen Funktionen gewartet werden (hier a()
).
info> Der folgende Abschnitt ist für Experten, die versuchen innerhalb von Objekten asynchrone Funktionen, wie etwa das Nachladen von Daten, aufzurufen.
Soweit so gut. Kommen wir zu den schlechten Nachrichten. Das Laden von Bildern oder anderen Daten von Webservern wird nicht von JavaScript selbst sondern vom Browser übernommen. Daher hat JavaScript hier auch keinerlei Motivation zu warten und macht schonmal weiter. Kann man sich vorstellen wir ein Bäcker der schonmal weiter macht, auch wenn der Teig noch nicht geknetet ist. Hier also nicht hilfreich.
Um das Laden von externen Inhalten zu erleichtern, kann etwa axios verwendet werden:
axios.get('/user?id=12345')
.then(function (response) {
// Bei erfolgreicher Antwort (HTTP-Code 200)
console.log(response);
})
.catch(function (error) {
// Bei Fehler vom Server (etwa HTTP-Code 404)
console.log(error);
});
Super, das fügen wir jetzt in eine Klasse ein:
class loader {
load() {
axios.get('/user?id=12345')
.then(function (response) {
// Bei erfolgreicher Antwort (HTTP-Code 200)
this.response = response;
})
.catch(function (error) {
// Bei Fehler vom Server (etwa HTTP-Code 404)
console.log(error);
})
}
}
loader.load();
console.log(loader.response); // leider leer :-(
Was passiert hier. Wir legen innerhalb der Klasse loader
die Variable response
an und wollen da den eben vom Server angeforderten Benutzer (user
) abspeichern.
Das führt aus folgenden Grund zu einem Fehler: Innerhalb der asynchron ausgeführten Funktion then
gilt das Schlüsselwort this
nicht mehr.
So können wir das lösen:
class loader {
load() {
var self = this //Hier setzen wir eine Referenz
axios.get('/user?id=12345')
.then(function (response) {
// Bei erfolgreicher Antwort (HTTP-Code 200)
self.response = response;
})
.catch(function (error) {
// Bei Fehler vom Server (etwa HTTP-Code 404)
console.log(error);
})
}
}
loader.load();
console.log(loader.response); // Benutzer