Does calling setTimeout clear the callstack?

末鹿安然 提交于 2019-12-17 12:49:08

问题


Can a stack overflow be avoided in javascript by using the setTimeout method to call a function instead of calling it directly? My understanding of setTimeout is that it should start a new callstack. When i look in the callstack of both chrome and IE it seems that the setTimeout calls are waiting for the function call to return.

Is this just a property of the debugger or is my understanding flawed?

EDIT

While the answers provided below are correct, the actual problem I was having was related to the fact that I was calling setTimeout(aFunction(), 10) which was evaluating aFunction immediately because of the brackets. This question sorted me out.


回答1:


I can confirm that the stack is cleared.

Consider this scenario:

function a() {
     b();   
}

function b() {
     c();   
}

function c() {
    debugger;
    setTimeout( d, 1000 );
}

function d() {
    debugger;
}

a();

So there are two breakpoints - one at the beginning of function c, and one at the beginning of function d.

Stack at first breakpoint:

  • c()
  • b()
  • a()

Stack at second breakpoint:

  • d()

Live demo: http://jsfiddle.net/nbf4n/1/




回答2:


Async invocations, such as those from setTimeout, do indeed generate a new callstack.

It's not entirely clear what you're describing when you say "When i look in the callstack of both chrome and IE it seems that the setTimeout calls are waiting for the function call to return." But, one thing you can do is put a breakpoint inside of a function called by setTimeout, and see that the callstack is empty.




回答3:


There's another way to clear the call stack without using setTimeout():

testLoop.js

let counter = 0;
const max = 1000000000n  // 'n' signifies BigInteger
Error.stackTraceLimit = 100;

const A = () => {
  fp = B;
}

const B = () => {
  fp = A;
}

let fp = B;

const then = process.hrtime.bigint();

loop:   // label is not needed for this simple case though useful for some cases
for(;;) {
  counter++;
  if (counter > max) {
    const now = process.hrtime.bigint();
    const nanos = now - then;

    console.log({ "runtime(sec)": Number(nanos) / (1000000000.0) })
    throw Error('exit')
  }
  fp()
  continue loop;
}

output:

$ node testLoop.js
{ 'runtime(sec)': 20.647399601 }
C:\Users\jlowe\Documents\Projects\clearStack\testLoop.js:25
    throw Error('exit')
    ^

Error: exit
    at Object.<anonymous> (C:\Users\jlowe\Documents\Projects\clearStack\testLoop.js:25:11)
    at Module._compile (internal/modules/cjs/loader.js:776:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:829:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)


来源:https://stackoverflow.com/questions/8058612/does-calling-settimeout-clear-the-callstack

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!