ALD*_*ENT 65 javascript event-loop async-await
let x = 0;
async function test() {
x += await 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);Run Code Online (Sandbox Code Playgroud)
x记录的值为1和5。我的问题是:为什么x 5第二个日志的值是?
如果test是后执行x += 1(因为它是一个异步函数),那么价值x是1由时间test执行,所以x += await 5应的值x 6。
FZs*_*FZs 62
TL;DR:因为在它的第二个操作数(右侧)中有关键字,所以先+=读取x,但在更改后写入await。
async函数在调用时同步运行,直到第一条await语句。
所以,如果你 remove await,它的行为就像一个普通的函数(除了它仍然返回一个 Promise )。
在这种情况下,您将在控制台中获得5(从函数)和6(从主脚本):
let x = 0;
async function test() {
x += 5;
console.log('x :', x);
}
test();
x += 1;
console.log('x :', x);Run Code Online (Sandbox Code Playgroud)
第一个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);Run Code Online (Sandbox Code Playgroud)
但是,您的情况要复杂一些。
你已经放入await了一个表达式,它使用+=.
您可能知道,JSx += 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);Run Code Online (Sandbox Code Playgroud)
当口译员到达这一行时......
x = (x + await 5);
Run Code Online (Sandbox Code Playgroud)
...它开始评估它,替代品x,所以它变成...
x = (0 + await 5);
Run Code Online (Sandbox Code Playgroud)
...然后,它到达await并停止。
函数调用后的代码开始运行,修改 的值x,然后记录下来。
x现在是1。
然后,在主脚本退出后,解释器返回到暂停的test函数,并继续评估该行:
x = (0 + 5);
Run Code Online (Sandbox Code Playgroud)
并且,由于 的值x已经被替换,它仍然是0。
最后,解释器进行添加、存储5到x并记录它。
您可以通过在对象属性 getter/setter 中登录来检查此行为(在本例中,y.z,它反映了 的值x:
x = (x + await 5);
Run Code Online (Sandbox Code Playgroud)
x = (0 + await 5);
Run Code Online (Sandbox Code Playgroud)
Ber*_*rgi 11
你的声明x += await 5脱糖
const _temp = x;
await;
x = _temp + 5;
Run Code Online (Sandbox Code Playgroud)
该_temp的卵巢值是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 printingRun Code Online (Sandbox Code Playgroud)
所以,代码实际上并没有直接进行,这是肯定的。我们也有一件奇怪的4/7事情。这就是问题的全部。
首先,让我们澄清-异步函数没有真正严格asynchronious。如果使用await关键字,它们只会暂停执行并稍后恢复。没有它,它们会从上到下同步执行,一个接着一个表达式:
async function foo() {
console.log("--one");
console.log("--two");
}
console.log("start");
foo();
console.log("end");Run Code Online (Sandbox Code Playgroud)
async function foo() {
console.log("--one");
await 0; //just satisfy await with an expression
console.log("--two");
}
console.log("start");
foo();
console.log("end");Run Code Online (Sandbox Code Playgroud)
因此,我们首先需要知道的是 usingawait将使函数的其余部分稍后执行。在给定的示例中,这意味着console.log('x1 :', x)将在其余同步代码之后执行。这是因为在当前事件循环完成后,任何 Promise 都会被解决。
所以,这就是为什么我们得到x2 : 1记录第一,为什么x2 : 5会记录第二然而不知其所以然后者价值5。逻辑上x += await 5应该是5...但这里是await关键字的第二个捕获- 它会暂停函数的执行,但在它已经运行之前的任何事情。x += await 5实际上将按以下方式处理
x。在执行时,那是0。await下一个表达式是5. 因此,功能现在暂停,稍后将恢复。0 + 5x因此,该函数在读取xis后暂停,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 printingRun Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2834 次 |
| 最近记录: |