function foobar() {
console.log('baz');
setTimeout(() => foobar(), 1000);
}
foobar();
throw new Error('terminate');
我假设foobar
函数对在1s之后执行的回调进行排队,退出堆栈,然后main函数抛出错误,事情应该终止。但是,如果在浏览器中运行则不会。
这个例子更好地说明了这一点:
let attempts = 10;
function foobar() {
if (!attempts--) return; // make it stop!
console.log('baz');
setTimeout(foobar, 1000);
throw new Error('terminate');
}
foobar();
请参阅抛出错误会终止当前任务的执行,但不会终止浏览器event loop。并且事件循环已经在其队列中有另一个任务 - 在抛出Error之前由setTimeout调度。冲洗并重复。
然而,Node.js中的情况有所不同:第一个未捕获的异常基本上停止了整个过程的执行。这就是Node的哲学 - fail early - 尽管questioned,但它的存在方式却是如此。
不过,经过微小的修改,你会看到类似的图片。只需将这些行添加到脚本中:
process.on('uncaughtException', function (err) {
console.error('CAUGHT', err);
});
......你会看到非常相似的模式。
成为JavaScript解释器。
让我们看一下任务列表,JavaScript解释器必须做的事情:
[执行主要代码]
现在解释器逐行执行任务。
执行foobar();
JavaScript解释器将在其任务列表中推送一个新任务,该任务列表包含要执行的setTimeout()
函数。
[执行主代码(进行中)] [执行setTimeout函数]
然后当它到达throw时,它会抛出一个错误并终止实际的任务执行。
它需要执行下一个任务并执行它:
[执行setTimeout函数(进行中)]
执行setTimeout
函数,它再次推送一个新任务(它刚刚执行)。
又一次又一次又一次......
function foobar() {
console.log('baz');
setTimeout(() => foobar(), 1000);
}
foobar();
throw new Error('terminate');