Как увеличить максимальный стек вызовов в JavaScript?
у меня есть событие, которое может стрелять сам. Я стараюсь сделать код как можно более эффективным, но в некоторых обстоятельствах он может ударить по максимальному стеку вызовов, который я не контролирую. Это не бесконечный стек, и он закончится в какой-то момент, но иногда он может потенциально разбиться, прежде чем он закончится из-за предела.
увеличу ли я количество стека вызовов, если я настрою 2 подобных прослушивателя событий и разделю код? Или что я могу делать?
обновление: это событие изменения DOM (работает только с Webkit, поэтому не заботьтесь о других браузерах), которое также может изменить DOM на основе некоторых условий. Я еще не достиг этого предела, но теоретически он потенциально может. Я все еще оптимизирую код, чтобы сделать как можно меньше манипуляций DOM.
обновление 2: Я включаю пример (не реальный) пример:
document.addEventListener('DOMSubtreeModified', function(event){
this.applyPolicy(event);
}, true);
function applyPolicy(event){
if( typeof event != "undefined" ){
event.stopPropagation();
event.stopImmediatePropagation();
}
if( !isButtonAllowed ){
$('button:not(:disabled)').each(function(){
$(this).attr('disabled', true);
});
}
}
Это просто пример кода, но даже в этом если у вас есть, скажем, 100 кнопок, стек вызовов также будет в 100s. Обратите внимание, что если вы используете $('button').attr('disabled', true);
, это вызовет проблему стека вызовов, потому что jQuery будет пытаться бесконечно изменять DOM.
6 ответов
хотя это звучит так, как будто вам может потребоваться переосмыслить некоторый код, одной из возможностей было бы поместить рекурсивный вызов в setTimeout
на некотором заданном интервале. Это позволяет начать новый стек вызовов.
возьмем такой пример...
var i = 0;
function start() {
++i;
var is_thousand = !(i % 1000);
if (is_thousand)
console.log(i);
if (i >= 100000)
return; // safety halt at 100,000
else
start()
}
он просто входит в консоль на каждом интервале 1,000
. В Chrome он превышает стек где-то в
для любого браузера максимальный стек вызовов работает хорошо в тысячи. Вы должны попытаться оптимизировать код, имея огромный стек вызовов, не подходит для скорости и памяти.
Если вы столкнулись с этим, это индикатор, что ваш код остро нуждается в реорганизации
размер callstack и детали реализации будут зависеть от среды JavaScript, в которой работает ваш код. Даже если вы можете управлять использованием стека для работы в средах, которые вам сейчас небезразличны, есть большая вероятность, что стек-голодный код аварийно завершит работу при запуске в среде, которая предоставляет другой размер стека.
любая рекурсивная программа может быть переписана как итеративная. Подумайте, сможете ли вы сделать это в вашем случае. См.:
вы Не могу, они зависят от браузера и, честно говоря, у них довольно широкий диапазон, поэтому не нужно беспокоиться об этом IMO.
Если вы нажимаете ограничение стека вызовов, у вас почти наверняка есть рекурсивная серия событий. События зависят от стека, поэтому они действительно не лучший способ реализации цикла. На языке без исключения хвостового вызова ваш единственный реальный вариант-использовать стандартные конструкции цикла, такие как for/in.
узнав, что вы подвергаете цензуре сторонний код, который может представлять элементы, которые вы не хотите отображать, я понимаю реальную корневую проблему:черные никогда работа над ненадежным кодом в итоге код будет обойти черный список и все дела.
вне перехода код так, чтобы никакой сторонний код не ожидает (или) доступ к DOM, мое решение будет выглядеть следующим образом:
- дублировать ваш DOM в скрытый iframe.
- песочница стороннего кода в указанном iframe.
- при любом изменении DOM в iframe проверьте iframe на наличие различий между двумя деревьями DOM. Если изменение проходит белый, потяните его в свой реальный DOM (повторное присоединение обратных вызовов событий и так далее).
- скопируйте структуру "реального" DOM после обновлений в iframe DOM, очистив любые конфиденциальные данные от него в процесс.
вы все равно проверите событие DOM в iframe, но вы не будете на своей "фактической" странице, поэтому вы не можете ввести бесконечный цикл.
Это предполагает, что вы действительно не могу доверяйте своему стороннему коду, чтобы делать то, что он должен делать. Если это просто некомпетентность поставщика, забудьте часть очистки,но придерживайтесь белого списка вместо черного списка.