我创建了两个JS程序来测试JavaScript调用堆栈,事件队列和Timer请求处理程序异步API的本质。
情景#1。
function logFirst(){
console.log('First');
}
function logThird() {
for (var i = 0; i <= 999999999; i++) {
if (i == 999999999) {
console.log("Third");
}
}
}
logFirst(); //first sync function
setTimeout(function() {
console.log('Second');
}, 0);
logThird(); //painfully slow sync function called
&#13;
此程序执行First,然后继续遇到setTimeout,这是一个异步任务。由于此任务是异步的,因此它由浏览器的Timer Handler API处理,它执行一个0秒的计时器,然后将传递给setTimeout的匿名回调函数排入浏览器的事件队列。
但是直到所有这一切发生,第三个函数,一个阻塞的代码logThird()已经被调用。调用堆栈很忙,因为迭代需要花费大量时间才能完成。在最后一次迭代中,&#34;第三次&#34;打印到控制台。
当logThird()完成后,执行调用堆栈变得空闲,并且事件队列中的回调现在被推送到调用堆栈,然后执行。
场景#2。 我创建了两种阻塞类型的函数,如下所示:
function logFirst(){
console.log('First');
}
function logThird() {
for (var i = 0; i <= 999999999; i++) {
if (i == 999999999) {
console.log("Third");
}
}
}
function logFourth() {
for (var i = 0; i <= 999999999; i++) {
if (i == 999999999) {
console.log("Fourth");
}
}
}
logFirst(); //first sync function
setTimeout(function() { // an async task
console.log('Second');
}, 0);
logThird(); //painfully slow sync function called
//isn't the call stack free at this point in time?
logFourth(); //another painfully slow sync function called
&#13;
然后我假设在logThird完成执行之后以及在logFourth被推送到调用堆栈之前调用堆栈将为空时运行此代码。所以&#34;第二&#34;应该是第三次打印。但最后打印出来了。
(请在全屏模式下运行两个片段以便能够看到JS控制台输出)
为什么异步回调没有被推入调用堆栈?
答案 0 :(得分:0)
在logThird完成执行之后以及在将logFourth推送到调用堆栈之前,调用堆栈将为空
不,仍有全局执行上下文(堆栈帧)运行您的脚本,并通过调用它实际上将logFourth
推送到堆栈上。如果没有这样的东西(诚然,它不是函数执行上下文),脚本的每个语句都必须经历事件循环本身。