What i all know about call stack is:
If there is only one function being called it will be pushed to call stack and removed when its job is done or otherwise return statement is encountered.
If one function calls another one, both stays in call stack and popped out in a order; children then parent.
If there is asynchronous code in child function, both are popped out as said in statement 2. but when the asynchronous job is done in future, then child (?) function will be put into Task Queue and then into Call Stack.
But when i used debugger in VSCode:
- I found that both parent and child functions are in call stack after completion of
setTimeout(). making my belief false of only child being in call stack. - In below code after resolve of promise only const
dummy2 = 'abc'is available in debugger after completion of asynchronous code, and not the constdummy = 'XYZ'
function asyncfun(){
const innerDummy = '123'
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('You are eligible for voting.');
},5000)
})
}
function outer(){
const dummy = 'XYZ';
asyncfun().then((msg)=>{
const dummy2 = 'abc'
console.log('Promise result:',msg)
})
}
outer();
Note that i had put breakpoints on line:
resolve('You are eligible for voting.');insidesetTimeOut()callback, to see who is in call stack after completion/resolve of promise, which happens in 5 seconds in future. Meanwhile when execution reaches to this line,innerDummyis not available to use.Another breakpoints on line
console.log('Promise result:',msg)where execution reaches after the above one. Heredummyis not available to use butdummy2is.Because of above variables not available for in debugger i am confused whether partial functions are re-pushed to call stack or what?
I think you might be confusing the concepts of call stack and scoping here a little bit.
The completion of setTimeout here is instant, since you're just returning a promise that will be pushed on to the task queue. At that point your callstack should contain
outer=>asyncfunc.You return the promise from
asyncfuncand outer is done as far as the synchronous part of the execution is concerned. Then after the timeout passes, internally the JS engine pushes the timeout callback on to the task queue. Conceptually your task queue at that point only contains that anonymous callback of setTimeout, but some debuggers show async differently and sometimes you can see the trace of where the callback was handled (this will be different for different JS implementations like Node, Deno or Chrome, since callback handling isn't really a part of the JS language, which only by itself is synchronous).I'm assuming your breakpoint here is somewhere around
console.log('Promise result:', msg). If that's the case, both yourdummyanddummy2variables will be available (you can check that by console logging them after thedummy2declaration), butdummyis not part of your local scope, so you should see it under Closure in the debug panel.So to answer your main question - no, only the async callback gets pushed to the call stack by the task queue. Basically only this
ends in your callstack after the timeout is done. If you're asking about what happens with the function after
.then(..), that's handled a bit differently in a so-called "Microtask queue". It might be helpful dropping your code in here https://www.jsv9000.app/ to visually check how your execution looks.Hope that helps :)