繁体   English   中英

为什么setTimeout出现在其回调中的错误的堆栈跟踪中

[英]Why is setTimeout shows up in stack trace of error thrown into its callback

考虑以下代码:

setTimeout(()=>{
    throw new Error("Testing error");
},100)

我在chrome控制台中运行此代码我得到了这个:

Uncaught Error: Testing error
at setTimeout (<anonymous>:2:15)

但我没想到会在那里看到setTimeout 这是因为setTimeout在调用堆栈上运行回调之前已经从callstack中移除了100ms。

有人可以解释一下吗?

我没想到会在那里看到setTimeout 这是因为setTimeout在调用堆栈上运行回调之前已经从callstack中移除了100ms。

正确,它不在调用堆栈上。

有人可以解释一下吗?

Chrome只是想在这里提供帮助。 它为匿名箭头函数派生了一个名称 - 从创建它的行开始。 检查整个调用堆栈(通过单击展开箭头):

setTimeout @ VM4560:2

(anonymous) @ VM4560:1

斜体setTimeout (async) (以及下面的所有内容)来自异步堆栈跟踪 它确实记得调度抛出异常的回调位置:使用setTimeout ,来自控制台上下文。

让我们试试吧

function example(cb) {
    setTimeout(cb, 100);
}
example(() => {
    throw new Error("Testing error");
});

我们会得到的

example    @   VM4562:5

example @   VM4562:2
(anonymous) @   VM4562:4

同样,回调是在传递给它的函数之后命名的 - example在这种情况下。 可以在异步堆栈跟踪中找到原始example()调用。

我们可以使用命名函数表达式来澄清:

setTimeout(function callback() {
    throw new Error("Testing error");
}, 100);

现在我们得到了预期

callback @ VM4564:2

(anonymous) @ VM4564:1

这是因为setTimeout在调用堆栈上运行回调之前已经从callstack中移除了100ms

这可以追溯到setTimout()工作原理。

众所周知,javascipt是​​一种单线程编程语言,这告诉我们setTimout()不是JS的一部分或(v8)javascript运行时,但它是浏览器提供的webapi的一部分。

现在,当我们调用setTimout()它被推送到堆栈,你所提供的回调是什么把它推送到webapi然后它从堆栈中删除,现在webapi是那个做所有等待的人,因为它是另一个线程由浏览器提供。

文件延迟完成后,回调被推送到堆栈队列然后事件循环开始,偶数循环所做的是继续等待堆栈被清空,然后它开始使队列堆栈出列并将其推回堆栈。

所以你所看到的是完全正常的,它似乎并不正确。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM