TL; DR: Weil zuvor +=
gelesen x
, aber geschrieben, nachdem es sich geändert hat, aufgrund des await
Schlüsselworts in seinem zweiten Operanden (rechts).
async
Funktionen werden synchron ausgeführt, wenn sie bis zur ersten await
Anweisung aufgerufen werden .
Wenn Sie also entfernen await
, verhält es sich wie eine normale Funktion (mit der Ausnahme, dass es immer noch ein Versprechen zurückgibt).
In diesem Fall erhalten Sie 5
und 6
in der Konsole:
let x = 0;
async function test() {
x += 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
Der erste await
Vorgang stoppt die synchrone Ausführung, auch wenn sein Argument synchron verfügbar ist. Daher wird Folgendes zurückgegeben 1
und 6
wie erwartet:
let x = 0;
async function test() {
// Enter asynchrony
await 0;
x += 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
Ihr Fall ist jedoch etwas komplizierter.
Sie haben await
einen Ausdruck eingefügt, der verwendet +=
.
Sie wissen wahrscheinlich, dass in JS x += y
identisch ist mit x = (x + y)
. Ich werde das letztere Formular zum besseren Verständnis verwenden:
let x = 0;
async function test() {
x = (x + await 5);
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
Wenn der Dolmetscher diese Zeile erreicht ...
x = (x + await 5);
... es beginnt es zu bewerten und es dreht sich um ...
x = (0 + await 5);
... dann erreicht es das await
und hört auf.
Der Code nach dem Funktionsaufruf wird ausgeführt, ändert den Wert von x
und protokolliert ihn anschließend.
x
ist jetzt 1
.
Nach dem Beenden des Hauptskripts kehrt der Interpreter zur angehaltenen test
Funktion zurück und setzt die Auswertung dieser Zeile fort:
x = (0 + 5);
Und da der Wert von x
bereits ersetzt ist, bleibt er bestehen 0
.
Schließlich führt der Interpreter die Addition durch, speichert 5
sie x
und protokolliert sie.
Sie können dieses Verhalten überprüfen, indem Sie sich in einem Objekt-Eigenschafts-Getter / -Setter anmelden (in diesem Beispiel wird y.z
der Wert von x
:
let x = 0;
const y = {
get z() {
console.log('get x :', x);
return x;
},
set z(value) {
console.log('set x =', value);
x = value;
}
};
async function test() {
console.log('inside async function');
y.z += await 5;
console.log('x :', x);
}
test();
console.log('main script');
y.z += 1;
console.log('x :', x);
/* Output:
inside async function
get x : 0 <-- async fn reads
main script
get x : 0
set x = 1
x : 1
set x = 5 <-- async fn writes
x : 5 <-- async fn logs
*/
/* Just to make console fill the available space */
.as-console-wrapper {
max-height: 100% !important;
}
await (x += 5)
und kennenx += await 5
.