TL; DR: 2番目のオペランド(右側)のキーワードが原因で、変更前に+=
読み取りx
、変更後に書き込みを行うためawait
。
async
関数は、最初のawait
ステートメントまで呼び出されたときに同期的に実行されます。
したがって、を削除await
すると、通常の関数のように動作します(ただし、Promiseを返す点が異なります)。
その場合、コンソールで次のように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
てログに記録します。
この動作を確認するには、オブジェクトプロパティのゲッター/セッター内でログを記録します(この例で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
ます。