考虑下面的两个函数,都是异步的,一个是占用大量时间的繁重工作负载,另一个是通过设置超时等待精确秒数的等待函数。
async function Brutal_Workload()
{
for(var x = 0; x< 1000 * 1000 * 1000; x++)
{
}
}
async function Time_Wait(seconds)
{
var promise = new Promise((resolve, reject) =>
{
var msecs = Math.floor(seconds * 1000);
var timer =
setTimeout(
function()
{
clearTimeout(timer);
resolve();
},
msecs);
});
return promise;
}
现在,让我们调用setInterval循环中的第一个函数
setInterval(
async function()
{
await Brutal_Workload();
console.log("BLIP");
}, 1000 / 30);
全部符合预期:尽管间隔以每秒30次调用的速度运行,但我每秒只得到1个blip,因为Brutal_Workload阻塞了它。
但是当我使用另一个功能时...
setInterval(
async function()
{
await Time_Wait(1);
console.log("BLIP");
}, 1000 / 30);
我每秒得到30个BLIP。Time_Wait函数在setInterval之外工作正常,但在这里似乎不工作。
知道是什么原因导致这种行为吗?
1条答案
按热度按时间cbeh67ev1#
好吧,与其继续在评论中来回,我只是要张贴这作为一个答案。
Javascript是单线程的 * 和 * 并发的。我知道你知道这一点,但你似乎没有意识到其中的含义。在你的第一个函数中,你只偶尔看到一个
console.log
,因为你的“残酷的工作负载”阻塞了唯一的执行线程,直到它完成,这意味着无论你传递给setInterval
的数字是多少,不仅没有其他调用在运行,下一项工作 * 甚至没有 * 排队 * 运行,因为您的繁重工作负载阻塞了 * 唯一的 * 执行线程 *。了解,运行时环境的
setInterval
运行在相同的因此,虽然工作负载很大,但setInterval
本身,更不用说你传递给它的函数,根本没有运行 *。使用async
并将繁重的工作负载 Package 在Promise中,就我们这里的讨论而言,基本上没有任何区别,因为繁重的工作负载占主导地位。这就解释了第一个例子,到目前为止一切顺利,继续第二个。
与第一个示例不同,在第二个示例中,没有长时间运行的代码块来束缚执行线程,因此您对
setInterval
的回调运行,忠实地注册了一个要在一秒钟内运行的东西,并 * 产生了对执行线程的控制 *。第一个例子也没有这里Promise和async/await
实际上 * 确实 * 启用了并发,而在第一个示例中它无法做到这一点,因为繁重的工作负载占据了线程。因此,在几分之一秒内,您对setInterval
的回调再次运行,并尽职尽责地排队等待一秒后运行另一个对象,以此类推。因此,在大约1秒后,第一个排队的日志发生,然后在几分之一秒后,第二个,依此类推。这不会发生在第一个例子中,因为虽然你告诉
setInterval
运行30倍/秒残酷的工作负载意味着setInterval
* 本身 * 不能运行,甚至 * 排队 * 您的回调运行。