为什么以下JS代码不会在浏览器中终止?

时间:2018-08-30 15:01:05

标签: javascript browser event-loop

function foobar() {
  console.log('baz');    
  setTimeout(() => foobar(), 1000);
}

foobar();
throw new Error('terminate');

我假设foobar函数将一个在1s之后执行的回调排队,然后退出堆栈,然后main函数抛出错误,并且应该终止。但是,如果它们在浏览器中运行,则不会。

2 个答案:

答案 0 :(得分:2)

此示例对此进行了更好的说明:

let attempts = 10;
function foobar() {
  if (!attempts--) return; // make it stop!
  console.log('baz');
  setTimeout(foobar, 1000);  
  throw new Error('terminate');
}
foobar();

请参见,引发错误会终止当前任务的执行,但不会终止浏览器event loop。事件循环中已经有另一个任务坐在队列中-由setTimeout 排定,然后抛出错误。冲洗并重复。


但是,Node.js领域的情况有所不同:第一个未捕获的异常基本上会停止整个进程的执行。这就是Node的理念-fail early-尽管questioned仍然存在。

仍然,只需进行少量修改,您就会看到类似的图片。只需将以下行添加到脚本中:

process.on('uncaughtException', function (err) {
  console.error('CAUGHT', err);
});

...,您会看到非常相似的模式。

答案 1 :(得分:1)

成为JavaScript解释器。

让我们看一下任务列表,JavaScript解释器必须这样做:


TaskList

[执行主代码]


现在,解释器逐行执行任务。

执行foobar();的JavaScript解释器将在其任务列表中推送一个新任务,其中包含要执行的setTimeout()函数。


TaskList

[执行主要代码(正在进行)] [执行setTimeout函数]


然后,当到达抛出时,它将抛出错误并终止实际的任务执行。

它需要执行下一个任务:


TaskList

[执行setTimeout函数(正在进行)]


执行setTimeout函数,它将再次推送一个新任务(与刚刚执行的任务相同)。

一次又一次,一次又一次...


    function foobar() {
      console.log('baz');    
      setTimeout(() => foobar(), 1000);
    }
    
    foobar();
    throw new Error('terminate');