Ошибка "слишком много рекурсии" в Firefox только иногда? - PullRequest
12 голосов
/ 30 июля 2011

У меня есть довольно простая вещь, которую я делаю с 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, которая не 't показано).

В любом случае, когда возникает слишком большая ошибка рекурсии, она будет продолжаться до тех пор, пока я не перезапущу Firefox.когда я перезапускаю Firefox, все снова работает как обычно.Как это исправить?

Я также сделал jsbin пример

Обновление

Хорошо, я нашел, как надежно воспроизвести егов нашем коде, но это не работает для примера jsbin.Если я создаю новую вкладку и перехожу на одну и ту же страницу (у меня две вкладки с одинаковым адресом), а затем обновляю первую вкладку два раза, я получаю эту ошибку последовательно.Мы не используем какой-либо сеанс или что-либо еще, о чем я могу подумать, что это может привести к возникновению такой проблемы только в одной вкладке!

Обновление 2 Не так надежно, как я думал,но это определенно происходит только тогда, когда открыто более одной вкладки на одной странице.Это будет происходить каждые несколько перезагрузок одной из открытых вкладок

Я также обновил свой код, чтобы показывать предупреждение, когда pageLoad (оператор if) изначально не определен и когда он изначально определен.Почему-то оба оповещения появляются.Этот код не дублируется на отображаемой странице, и его нельзя вызвать дважды.Он находится в элементе скрипта верхнего уровня, не окруженном функцией или чем-либо еще!Мой код выглядит как

if(pageLoad===undefined){ 
  var pageLoad=function(){}; 
  alert('new'); 
} else {  
  alert('old'); 
}

Ответы [ 6 ]

7 голосов
/ 30 июля 2011

Рассматриваемый код - сам по себе - должен никогда приводить к бесконечной проблеме рекурсии - нет оператора-функции, и все функциональные объекты охотно назначаются на переменные. (Если pageload является первым неопределенным, ему будет назначена функция без операции, см. Следующий раздел.)

Я подозреваю, что есть дополнительный код / ​​события, которые вызывают поведение. Одна вещь, которую может вызвать, - это если скрипт / код запускается дважды в течение жизни страницы. 2-й раз pageload не будет неопределенным и сохранит исходное значение, которое, если это функция, вызывающая две другие функции, приведет к бесконечной рекурсии.

Я бы порекомендовал очистить подход - и любые проблемы, вызванные осложнениями, просто исчезли ;-) Каково желаемое намерение?

Удачного кодирования.

2 голосов
/ 07 июля 2014

Это просто дополнительная информация для других людей, пытающихся найти похожие ошибки "слишком много рекурсии" в своем коде.Похоже, что 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.

1 голос
/ 04 апреля 2016

Я сталкивался с этой ошибкой.Сценарий в моем случае был другим.Код виновника был что-то вроде этого (простой рецессивный способ конкатенации)

while(row)
{
    string_a .= row['name'];
}

Я обнаружил, что JavaScript выдает ошибку на 180-й рекурсии.До цикла 179 код работает нормально.

Поведение в Safaris точно такое же, за исключением того, что отображается ошибка «RangeError: Превышен максимальный размер стека вызовов».Эта ошибка также генерируется при рекурсии 180.

Хотя это не связано с вызовом функции, но может помочь кому-то, кто застрял с ней.

0 голосов
/ 14 февраля 2019

Это также приведет к проблеме "слишком много рекурсии":

class account {
    constructor() {
        this.balance = 0;      // <-- property: balance
    }

    set balance( amount ) {    // <-- set function is the same name as the property.
        this.balance = amount; // <-- AND property: balance (unintended recursion here)
    }
}

var acc = new account();

Важно использовать уникальные имена.

Хорошо, так почему это происходит?

В функции set она на самом деле не устанавливает для свойства значение sum, вместо этого она снова вызывает функцию set, поскольку в области действия функции set одинаковый синтаксис как для установки свойства, так и для вызова функции set.

Поскольку в этой области this совпадает с account и (account OR this).balance = amount, оба могут вызвать функцию set ИЛИ установить свойство.

Решение этой проблемы - просто изменить имя свойства или функции set любым способом (и, конечно, соответствующим образом обновить остальную часть кода).

0 голосов
/ 14 октября 2015

Afaik, эта ошибка также может появиться, если вы укажете неверный параметр для своего запроса ajax, например

$.getJSON('get.php',{cmd:"1", elem:$('#elem')},function(data) { // ... }

, который вместо этого должен быть

elem:$('#elem').val()

.

0 голосов
/ 28 мая 2015

У меня такая же ошибка после обновления моего Firefox. Кажется, что версия Firefox вызывает проблемы, так как, когда я попробовал в других браузерах, таких как Chrome, он работает нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...