Вызывает ли setTimeout очистку стека вызовов? - PullRequest
12 голосов
/ 09 ноября 2011

Можно ли избежать переполнения стека в javascript с помощью метода setTimeout для вызова функции вместо ее непосредственного вызова? Насколько я понимаю, setTimeout заключается в том, что он должен начать новый стек вызовов. Когда я смотрю в стек вызовов chrome и IE, кажется, что вызовы setTimeout ожидают возврата вызова функции.

Это только свойство отладчика или мое понимание неверно?

EDIT

Хотя ответы, представленные ниже, являются правильными, реальная проблема, с которой я столкнулся, была связана с тем, что я вызывал setTimeout (aFunction (), 10), который сразу вычислял функцию из-за скобок. Этот вопрос разобрался со мной.

Ответы [ 3 ]

16 голосов
/ 09 ноября 2011

Я могу подтвердить, что стек очищен.

Рассмотрим этот сценарий:

function a() {
     b();   
}

function b() {
     c();   
}

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

function d() {
    debugger;
}

a();

Таким образом, есть две точки останова - одна в начале функции c и одна в начале функции d.

Стек в первой точке останова:

  • с ()
  • б ()
  • а ()

Стек на второй точке останова:

Демонстрационная версия: http://jsfiddle.net/nbf4n/1/

5 голосов
/ 09 ноября 2011

Асинхронные вызовы, например, из setTimeout, действительно генерируют новый стек вызовов.

Не совсем понятно, что вы описываете, когда говорите «Когда я смотрю в стек вызовов как chrome, так иIE кажется, что вызовы setTimeout ожидают возврата вызова функции. "Но одну вещь, которую вы можете сделать, это поместить точку останова в функцию, вызываемую setTimeout, и увидеть, что коллстак пуст.

0 голосов
/ 11 июля 2019

Есть еще один способ очистить стек вызовов без использования 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;
}

выход:

$ 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)
...