简体   繁体   中英

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

Consider following code:

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

I ran this code in chrome console I got this:

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

But I wasn't expecting to see setTimeout there. This is because setTimeout has already been removed from callstack 100ms before its callback was run on call stack.

Can someone explain this?

I wasn't expecting to see setTimeout there. This is because setTimeout has already been removed from callstack 100ms before its callback was run on call stack.

Correct, it's not on the call stack.

Can someone explain this?

Chrome is just trying to be helpful here. It derives a name for the anonymous arrow function - from the line where it was created. Inspect the whole call stack (by clicking on the expand arrow):

setTimeout @ VM4560:2
setTimeout (async)
(anonymous) @ VM4560:1

The italic setTimeout (async) (and everything below) comes from asynchronous stack traces . It does indeed remember from where the callback that threw the exception was scheduled: with setTimeout , from the console context.

Let's instead try

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

and we will get

example    @   VM4562:5
setTimeout (async)
example @   VM4562:2
(anonymous) @   VM4562:4

Again, the callback is named after the function it was passed to - example in this case. The original example() call can be found in the async stack trace.

We could use a named function expression instead to clarify:

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

Now we get the expected

callback @ VM4564:2
setTimeout (async)
(anonymous) @ VM4564:1

This is because setTimeout has already been removed from callstack 100ms before its callback was run on call stack

This is going back to how setTimout() work.

As we all know javascipt is a single threaded programming language, this tells us that setTimout() is not a part of JS or (v8) the javascript runtime, But it is part of the webapi provided by the browser.

Now when we call setTimout() it get's pushed to the stack what is does is takes the callback you provided push it to the webapi then it gets removed from the stack, now the webapi is the one doing all the waiting because it is another thread provided by the browser.

Wen the delay is done the callback gets pushed to the stack queue then the event loops kicks in, what the even loop does is keep waiting for the stack to be emptied and then it starts dequeuing queue stack and push it back to the stack.

So what you're seeing is totally normal it just doesn't seem right.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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