let x = 0;
async function test() {
x += await 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);
x
기록 된 값 은 1
및 5
입니다. 내 질문은 : 왜 x
5
두 번째 로그 의 값 입니까?
이 경우 test
후에 실행된다 x += 1
(이것은 비동기 함수이기 때문에)를 x의 값은 시간에 의해 1 test
실행되므로, x += await 5
의 값을 확인한다 x
6
.
답변
TL; DR : 때문에 +=
판독 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
, 그것을 기록합니다.
객체 속성 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;
}
답변
당신의 진술 x += await 5
은
const _temp = x;
await;
x = _temp + 5;
_temp
orary 값은 0
, 그리고 당신이 변경되면 x
시 await
(코드가 수행하는)이이 할당됩니다, 중요하지 않습니다 5
이후.
답변
이 코드는 예상치 못한 비동기 점프가 앞뒤로 걸리기 때문에 따르기가 매우 복잡합니다. 실제로 어떻게 실행되는지 살펴보고 (이후) 그 이유를 설명하겠습니다. 또한 콘솔 로그를 변경하여 숫자를 추가했습니다. 콘솔 로그를 쉽게 참조하고 기록 된 내용을 더 잘 보여줍니다.
let x = 0; // 1 declaring and assigning x
async function test() { // 2 function declaration
x += await 5; // 4/7 assigning x
console.log('x1 :', x); // 8 printing
}
test(); // 3 invoking the function
x += 1; // 5 assigning x
console.log('x2 :', x); // 6 printing
따라서 코드는 실제로 똑바로 진행되지는 않습니다. 그리고 우리에게는 이상한 4/7
것도 있습니다. 그리고 그것은 실제로 문제의 전체입니다.
우선, 비동기 함수는 실제로 엄격하게 비동기 적이 지 않습니다 . await
키워드가 사용 된 경우에만 실행을 일시 중지하고 나중에 다시 시작 합니다. 그것없이, 그들은 식에서 동기식으로 위에서 아래로 실행합니다.
async function foo() {
console.log("--one");
console.log("--two");
}
console.log("start");
foo();
console.log("end");
async function foo() {
console.log("--one");
await 0; //just satisfy await with an expression
console.log("--two");
}
console.log("start");
foo();
console.log("end");
그래서, 먼저 우리가 사용하는 것을 알아야 await
할 것입니다 나머지 함수의 나중에 실행합니다. 주어진 예에서, 이는 나머지 동기 코드 이후console.log('x1 :', x)
에 실행될 것임을 의미합니다 . 현재 이벤트 루프가 완료되면 약속이 해결되기 때문입니다.
우리가받을 이유 그래서,이 설명 x2 : 1
로그인 한 첫 번째 이유는 x2 : 5
두 번째 기록되지만 후자의 값이없는 이유 5
. 논리적 x += await 5
이어야한다 5
여기 …하지만 것은 두 번째 캐치입니다 await
키워드 – 그것은 것이다 일시 정지 이미 실행되기 전에 함수의 실행 아무것도하지만. x += await 5
실제로 다음과 같은 방식으로 처리됩니다
- 의 값을 가져옵니다
x
. 실행 당시는0
입니다. await
다음 표현식5
. 이제 기능이 일시 중지되고 나중에 다시 시작됩니다.- 기능을 재개하십시오. 표현은 5로 해결됩니다.
- 1의 값과 2/3의 식을 추가하십시오.
0 + 5
- 값을 4에서
x
따라서 함수 x
는 읽은 후에 일시 중지 0
되고 이미 변경되면 다시 시작되지만의 값을 다시 읽지 않습니다 x
.
우리 가 실행 await
하는 Promise
것과 동등한 것을 풀면 다음이 있습니다.
let x = 0; // 1 declaring and assigning x
async function test() { // 2 function declaration
const temp = x; // 4 value read of x
await 0; //fake await to pause for demo
return new Promise((resolve) => {
x = temp + 5; // 7 assign to x
console.log('x1 :', x); // 8 printing
resolve();
});
}
test(); // 3 invoking the function
x += 1; // 5 assigning x
console.log('x2 :', x); // 6 printing
답변
나중에 실제로 일어나는 일이 조금 까다 롭습니다. 추가 작업이 두 개씩 일어나고 있으므로 작업은 다음과 같습니다.
약속 내 : x += await 5
==> x = x + await 5
==> x = 0 + await 5
==>5
외부 : x += 1
==> x = x + 1
==> x = 0 + 1
==>1
위의 모든 동작이 왼쪽에서 오른쪽으로 일어나기 때문에 추가의 첫 번째 부분이 동시에 계산 될 수 있으며 5 이전에 대기 시간이 있기 때문에 additio가 비트를 지연시킬 수 있습니다. 코드 내에 중단 점을 넣어 실행을 확인할 수 있습니다.
답변
비동기 및 대기는 약속의 확장입니다. async 함수에는 async 함수의 실행을 일시 중지하고 전달 된 Promise의 해결을 기다린 다음 async 함수의 실행을 다시 시작하고 해결 된 값을 반환하는 await식이 포함될 수 있습니다. await 키워드는 비동기 함수 내에서만 유효합니다.
테스트 함수를 호출 한 후 x 값을 변경 한 경우에도 여전히 x 값은 0으로 남아 비동기 함수가 이미 새 인스턴스를 작성했기 때문입니다. 변수 외부의 변수에 대한 모든 변경 사항은 변수가 호출 된 후에 그 내부의 값을 변경하지 않음을 의미합니다. 증분을 테스트 기능 위에 두지 않는 한.