TL; DR: Parce que +=lit xavant, mais l'écrit après qu'il a changé, en raison du awaitmot - clé dans son deuxième opérande (côté droit).
asyncles fonctions s'exécutent de manière synchrone lors de leur appel jusqu'à la première awaitinstruction.
Donc, si vous supprimez await, il se comporte comme une fonction normale (à l'exception qu'il renvoie toujours une promesse).
Dans ce cas, vous obtenez 5et 6dans la console:
let x = 0;
async function test() {
x += 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
Le premier awaitarrête l'exécution synchrone, même si son argument est disponible de manière synchrone, donc ce qui suit reviendra 1et 6, comme vous vous y attendez:
let x = 0;
async function test() {
// Enter asynchrony
await 0;
x += 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
Cependant, votre cas est un peu plus compliqué.
Vous avez mis à l' awaitintérieur une expression, qui utilise +=.
Vous savez probablement que JS x += yest identique à x = (x + y). Je vais utiliser ce dernier formulaire pour une meilleure compréhension:
let x = 0;
async function test() {
x = (x + await 5);
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
Lorsque l'interprète atteint cette ligne ...
x = (x + await 5);
... il commence à l'évaluer, et il se transforme en ...
x = (0 + await 5);
... puis, il atteint le awaitet s'arrête.
Le code après l'appel de fonction commence à s'exécuter et modifie la valeur de x, puis l'enregistre.
xest maintenant 1.
Ensuite, après la fin du script principal, l'interpréteur revient à la testfonction suspendue et continue d'évaluer cette ligne:
x = (0 + 5);
Et, puisque la valeur de xest déjà substituée, elle reste 0.
Enfin, l'interprète fait l'ajout, les magasins 5à x, et l' enregistre.
Vous pouvez vérifier ce comportement en vous connectant à l'intérieur d'un getter / setter de propriété d'objet (dans cet exemple, y.zreflète la valeur de 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)etx += await 5.