Ошибка "слишком много рекурсии" в Firefox иногда?
У меня довольно простая вещь, которую я делаю с javascript, и в основном только иногда javascript дает мне ошибку "слишком много рекурсии".
Код, о котором идет речь:
if(pageLoad===undefined){
var pageLoad=function(){};
}
var pageLoad_uniqueid_11=pageLoad;
var pageLoad=function(){
pageLoad_uniqueid_11();
pageLoad_uniqueid_12();
};
var pageLoad_uniqueid_12=function(){
alert('pageLoad');
};
$(document).ready(function(){
pageLoad();
});
(да, я знаю, что есть лучший способ сделать это. Это сложно изменить, особенно из-за частичной обратной передачи ASP.Net, которые не показаны).
В любом случае, когда происходит слишком большая ошибка рекурсии, это продолжается до тех пор, пока я не перезапущу Firefox. когда я перезапускаю Firefox, все работает нормально. Как это исправить?
Я также сделал пример jsbin
Обновление
Хорошо, я узнал, как надежно воспроизвести его в нашем коде, но он не работает для примера jsbin. Если я создаю новую вкладку и перехожу на ту же страницу (имеют две вкладки с одним адресом), а затем обновляю первую вкладку два, тогда я получаю эту ошибку последовательно. Мы не используем какой-либо сеанс или что-то еще, о чем я могу думать, что может вызвать такую проблему только на одной вкладке!
Обновление 2
Не так надежно, как я думал, но это определенно происходит только тогда, когда открыто более одной вкладки одной и той же страницы. Это произойдет каждые несколько перезапуска одной из открываемых вкладок.
Я также обновил свой код, чтобы показать предупреждение, когда pageLoad (оператор if) первоначально undefined и когда он изначально определен. Так или иначе, появляются оба предупреждения. Этот код не дублируется на отображаемой странице, и нет способа, чтобы он вызывался дважды. Это элемент верхнего уровня script, не окруженный функцией или чем-либо еще! Мой код выглядит как
if(pageLoad===undefined){
var pageLoad=function(){};
alert('new');
} else {
alert('old');
}
Ответы
Ответ 1
Этот код сам по себе - никогда не должен приводить к бесконечной проблеме рекурсии - нет функционального оператора, и все функциональные объекты с нетерпением назначаются переменным. (Если pageload
- первый undefined, ему будет назначена функция No-Operation, см. Следующий раздел.)
Я подозреваю, что есть дополнительный код/события, вызывающие поведение. Одна вещь, которая может вызвать это, заключается в том, что script/код запускается дважды во время жизни страницы. Второй раз pageload
не будет undefined и сохранит исходное значение, которое, если оно является функцией, вызывающей две другие функции, приведет к бесконечной рекурсии.
Я бы рекомендовал очистить подход - и любые проблемы, вызванные осложнениями, просто исчезнут;-) Какое намерение у вас есть?
Счастливое кодирование.
Ответ 2
Это просто дополнительная информация для других людей, пытающихся найти похожие ошибки "слишком много рекурсии" в своем коде. Похоже, что firefox (в качестве примера) получает слишком много рекурсии около 6500 кадров стека в этом примере: function moose(n){if(n%100 === 0)console.log(n);moose(n+1)};moose(0)
. В аналогичных примерах можно увидеть глубину между 5000 и 7000. Не знаете, каковы определяющие факторы, но кажется, что количество параметров в функции резко уменьшает глубину кадра стека, в которой вы получаете ошибку "слишком много рекурсии". Например, это только до 3100:
function moose(n,m,a,s,d,fg,g,q,w,r,t,y,u,i,d){if(n%100 === 0)console.log(n);moose(n+1)};moose(0)
Если вы хотите обойти это, вы можете использовать setTimeout для планирования итераций, чтобы продолжить работу с планировщиком (который сбрасывает стек). Это, очевидно, работает только в том случае, если вам не нужно возвращать что-то из вызова:
function recurse(n) {
if(n%100 === 0)
setTimeout(function() {
recurse(n+1)
},0)
else
recurse(n+1)
}
Правильные хвостовые вызовы в ECMAScript 6 разрешат проблему для некоторых случаев, когда вам нужно что-то вернуть из таких вызовов. До тех пор, для случаев с глубокой рекурсией, единственными ответами пользуются либо итерация, либо метод setTimeout
, о котором я говорил.
Ответ 3
Я столкнулся с этой ошибкой. Сценарий в моем случае был другим. Код виновника был чем-то вроде этого (это простая конкатенация рецессивно)
while(row)
{
string_a .= row['name'];
}
Я обнаружил, что JavaScript выдает ошибку на 180-й рекурсии. До цикла 179 код работает нормально.
Поведение в Safaris точно такое же, за исключением того, что ошибка, которую он показывает, "RangeError: максимальный размер стека вызовов превышен". Он также выдает эту ошибку на 180 рекурсии.
Хотя это не связано с вызовом функции, но может помочь кому-то, кто застрял с ним.
Ответ 4
У меня такая же ошибка после обновления моего Firefox. Похоже, что версия Firefox вызывает проблему, поскольку, когда я пытался работать в других браузерах, таких как Chrome, он работает нормально.
Ответ 5
Afaik, эта ошибка также может появиться, если вы указали неверный параметр для своего запроса ajax, например
$.getJSON('get.php',{cmd:"1", elem:$('#elem')},function(data) { // ... }
Что должно быть
elem:$('#elem').val()
вместо.