Подтвердить что ты не робот

Ошибка "слишком много рекурсии" в 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'); 
}
4b9b3361

Ответ 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()

вместо.