事件队列中的JavaScript函数不会按预期移动到调用堆栈

时间:2017-03-09 12:36:47

标签: javascript asynchronous

我创建了两个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;
&#13;
&#13;

此程序执行First,然后继续遇到setTimeout,这是一个异步任务。由于此任务是异步的,因此它由浏览器的Timer Handler API处理,它执行一个0秒的计时器,然后将传递给setTimeout的匿名回调函数排入浏览器的事件队列。

但是直到所有这一切发生,第三个函数,一个阻塞的代码logThird()已经被调用。调用堆栈很忙,因为迭代需要花费大量时间才能完成。在最后一次迭代中,&#34;第三次&#34;打印到控制台。

当logThird()完成后,执行调用堆栈变得空闲,并且事件队列中的回调现在被推送到调用堆栈,然后执行。

场景#2。 我创建了两种阻塞类型的函数,如下所示:

&#13;
&#13;
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;
&#13;
&#13;

然后我假设在logThird完成执行之后以及在logFourth被推送到调用堆栈之前调用堆栈将为空时运行此代码。所以&#34;第二&#34;应该是第三次打印。但最后打印出来了。

(请在全屏模式下运行两个片段以便能够看到JS控制台输出)

为什么异步回调没有被推入调用堆栈?

1 个答案:

答案 0 :(得分:0)

  

在logThird完成执行之后以及在将logFourth推送到调用堆栈之前,调用堆栈将为空

不,仍有全局执行上下文(堆栈帧)运行您的脚本,并通过调用它实际上将logFourth推送到堆栈上。如果没有这样的东西(诚然,它不是函数执行上下文),脚本的每个语句都必须经历事件循环本身。