Вызывает ли setTimeout очистку стека вызовов?
Можно ли избежать переполнения стека в javascript с помощью метода setTimeout для вызова функции вместо ее непосредственного вызова? Насколько я понимаю, setTimeout заключается в том, что он должен начать новый стек вызовов. Когда я смотрю в стек вызовов chrome и IE, кажется, что вызовы setTimeout ожидают возврата вызова функции.
Это только свойство отладчика или мое понимание неверно?
РЕДАКТИРОВАТЬ
Хотя ответы, приведенные ниже, являются правильными, реальная проблема, с которой я столкнулся, была связана с тем, что я вызывал setTimeout(aFunction(), 10), который сразу вычислял функцию из-за скобок. Этот вопрос меня разобрал.
2 ответа
Я могу подтвердить, что стек очищен.
Рассмотрим этот сценарий:
function a() {
b();
}
function b() {
c();
}
function c() {
debugger;
setTimeout( d, 1000 );
}
function d() {
debugger;
}
a();
Таким образом, есть две точки останова - одна в начале функции c
и один в начале функции d
,
Стек на первой точке останова:
- с ()
- б ()
- а ()
Стек на второй точке останова:
- д ()
Демонстрация в реальном времени: http://jsfiddle.net/nbf4n/1/
Асинхронные вызовы, такие как из setTimeout
действительно создайте новый стек вызовов.
Не совсем понятно, что вы описываете, когда говорите: "Когда я смотрю в стек вызовов chrome и IE, кажется, что вызовы setTimeout ожидают возврата вызова функции". Но одна вещь, которую вы можете сделать, это поместить точку останова в функцию, вызываемую setTimeout
и увидите, что стек вызовов пуст.
Есть еще один способ очистить стек вызовов без использования 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)