TL; DR:เพราะ+=
อ่านx
มาก่อน แต่เขียนหลังจากเปลี่ยนไปเนื่องจากawait
คำสำคัญในตัวถูกดำเนินการตัวที่สอง (ด้านขวามือ)
async
ฟังก์ชั่นทำงานพร้อมกันเมื่อพวกเขาเรียกจนawait
คำสั่งแรก
ดังนั้นหากคุณลบออกawait
มันจะทำงานเหมือนฟังก์ชั่นปกติ (ยกเว้นว่ามันยังคงส่งคืนสัญญา)
ในกรณีนั้นคุณจะได้รับ5
และ6
อยู่ในคอนโซล:
let x = 0;
async function test() {
x += 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
ครั้งแรกที่await
หยุดการทำงานแบบซิงโครนัสแม้ว่าอาร์กิวเมนต์จะพร้อมใช้งานพร้อมกันดังนั้นสิ่งต่อไปนี้จะกลับมา1
และ6
ตามที่คุณคาดหวัง:
let x = 0;
async function test() {
// Enter asynchrony
await 0;
x += 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
อย่างไรก็ตามกรณีของคุณซับซ้อนกว่าเล็กน้อย
คุณได้ใส่ภายในนิพจน์ที่ใช้await
+=
คุณอาจจะรู้ว่าใน JS เป็นเหมือนx += y
x = (x + y)
ฉันจะใช้แบบฟอร์มหลังเพื่อความเข้าใจที่ดีขึ้น:
let x = 0;
async function test() {
x = (x + await 5);
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
เมื่อล่ามมาถึงบรรทัดนี้ ...
x = (x + await 5);
... มันเริ่มประเมินมันแล้วมันก็เปลี่ยนเป็น ...
x = (0 + await 5);
... จากนั้นจะถึงawait
และหยุด
รหัสหลังจากการเรียกใช้ฟังก์ชันเริ่มทำงานและแก้ไขค่าx
แล้วบันทึก
x
1
อยู่ในขณะนี้
จากนั้นหลังจากที่ออกจากสคริปต์หลักแล้วล่ามจะกลับไปที่test
ฟังก์ชันที่หยุดชั่วคราวและทำการประเมินบรรทัดนั้นต่อ:
x = (0 + 5);
และเนื่องจากค่าของแทนแล้วมันยังคงอยู่x
0
สุดท้ายล่ามไม่นอกจากนี้ร้านค้า5
ไปx
และบันทึกมัน
คุณสามารถตรวจสอบพฤติกรรมนี้ได้โดยการเข้าสู่ระบบภายในคุณสมบัติวัตถุ getter / setter (ในตัวอย่างนี้y.z
แสดงค่าของ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)
x += await 5