TL; DR: Karena +=
membaca x
sebelumnya, tetapi menulisnya setelah itu berubah, karena await
kata kunci dalam operan kedua (sisi kanan).
async
fungsi berjalan secara sinkron ketika mereka dipanggil hingga await
pernyataan pertama .
Jadi, jika Anda menghapus await
, berperilaku seperti fungsi normal (dengan pengecualian bahwa itu masih mengembalikan Janji).
Jika demikian, Anda masuk 5
dan 6
masuk ke konsol:
let x = 0;
async function test() {
x += 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
Yang pertama await
berhenti berjalan secara sinkron, meskipun argumennya tersedia secara sinkron, sehingga yang berikut akan kembali 1
dan 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 await
ekspresi yang digunakan +=
.
Anda mungkin tahu, bahwa di JS x += y
identik 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 await
dan berhenti.
Kode setelah panggilan fungsi mulai berjalan, dan mengubah nilai x
, lalu mencatatnya.
x
sekarang 1
.
Kemudian, setelah skrip utama keluar, interpreter kembali ke test
fungsi yang dijeda , dan terus mengevaluasi baris itu:
x = (0 + 5);
Dan, karena nilai x
sudah diganti, itu tetap 0
.
Akhirnya, penafsir melakukan penambahan, toko 5
untuk x
, dan log itu.
Anda dapat memeriksa perilaku ini dengan masuk ke dalam pengambil / penyetel properti objek (dalam contoh ini, y.z
mencerminkan 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
.