功能顺序有保证吗?
let x = 0;
function a() {
console.log("called a()");
for (let i=0; i<123456789; ++i) {
x += Math.sqrt(2);
}
console.log("x = "+x);
}
function b() {
x = undefined;
console.log("called b()");
}
setTimeout(b, 20);
a();
输出:
called a()
x = 174594265.7306214
called b()
b应该早点调用,但它一直等到函数a完成。
我知道 js 只使用一个线程,但处理器可以在执行a和执行b期间切换a。处理器是否总是一次只执行一个函数(如果里面没有 await)?在 nodejs 和网站 javascript 中?
编辑:
这是一个等待示例:
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
let x = 0;
async function a() {
console.log("called a()");
await sleep(1000);
for (let i=0; i<123456789; ++i) {
x += Math.sqrt(2);
}
console.log("x = "+x);
}
function b() {
x = undefined;
console.log("called b()");
}
setTimeout(b, 20);
a();
输出:
called a()
called b()
x = NaN
注意 x 如何变成 NaN,因为b在执行期间a
回答
b 应该早点被调用,但它一直等到函数 a 完成。
不b应该在同步代码执行后调用,因为那setTimeout是调用传递给的函数的时间。
的回调函数setTimeout计划在您指定为 的第二个参数的延迟之后运行setTimeout。此延迟是运行使用 调度的回调函数所需的最短时间setTimeout。
一旦计时器到期,该回调函数就会被放入一个任务队列,并从那里被推送到调用堆栈,但只有在调用堆栈为空时才会被推送。
在您的情况下,当您的脚本完成执行时,调用堆栈将为空。
我知道 js 只使用一个线程,但是处理器可以在 a 的执行过程中在执行 a 和 b 之间切换
只有 1 个线程是不可能的。在 Javascript 中,除非您使用另一个线程,否则在给定时间只执行一件事。
处理器是否总是一次只执行一个函数(如果里面没有 await)
是的。即使有await,函数也会暂停,直到承诺完成。一旦 promise 成立,该函数将继续执行,并且此时不会执行任何其他操作。
编辑
注意 x 是如何变成 NaN 的,因为 b 是在 a 期间执行的
不,这里没有干扰。函数a同步执行,直到出现以下语句
await sleep(1000);
在函数a暂停期间,等待 返回的promisesleep(...)来解决,在此期间,b由于其计时器已过期且调用堆栈为空,函数会被执行。
由于两个函数都分配给同一个变量x,因此 value of xisNaN因为它在函数a恢复之前的值isundefined并且执行加法undefined导致NaN.