TL; DR: Karena +=membaca xsebelumnya, tetapi menulisnya setelah itu berubah, karena awaitkata kunci dalam operan kedua (sisi kanan).
asyncfungsi berjalan secara sinkron ketika mereka dipanggil hingga awaitpernyataan pertama .
Jadi, jika Anda menghapus await, berperilaku seperti fungsi normal (dengan pengecualian bahwa itu masih mengembalikan Janji).
Jika demikian, Anda masuk 5dan 6masuk ke konsol:
let x = 0;
async function test() {
x += 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
Yang pertama awaitberhenti berjalan secara sinkron, meskipun argumennya tersedia secara sinkron, sehingga yang berikut akan kembali 1dan 6, seperti yang Anda harapkan:
let x = 0;
async function test() {
// Enter asynchrony
await 0;
x += 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
Namun, kasing Anda sedikit lebih rumit.
Anda telah memasukkan awaitekspresi yang digunakan +=.
Anda mungkin tahu, bahwa di JS x += yidentik dengan x = (x + y). Saya akan menggunakan formulir yang terakhir untuk pemahaman yang lebih baik:
let x = 0;
async function test() {
x = (x + await 5);
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
Ketika penerjemah mencapai garis ini ...
x = (x + await 5);
... mulai mengevaluasinya, dan ternyata menjadi ...
x = (0 + await 5);
... lalu, ia mencapai awaitdan berhenti.
Kode setelah panggilan fungsi mulai berjalan, dan mengubah nilai x, lalu mencatatnya.
xsekarang 1.
Kemudian, setelah skrip utama keluar, interpreter kembali ke testfungsi yang dijeda , dan terus mengevaluasi baris itu:
x = (0 + 5);
Dan, karena nilai xsudah diganti, itu tetap 0.
Akhirnya, penafsir melakukan penambahan, toko 5untuk x, dan log itu.
Anda dapat memeriksa perilaku ini dengan masuk ke dalam pengambil / penyetel properti objek (dalam contoh ini, y.zmencerminkan nilai dari 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)danx += await 5.