Ошибка превышения максимального размера стека вызовов - PullRequest
442 голосов
/ 23 мая 2011

Я использую файл библиотеки JavaScript Direct Web Remoting (DWR) и получаю сообщение об ошибке только в Safari (для ПК и iPad)

Там написано

Превышен максимальный размер стека вызовов.

Что именно означает эта ошибка и останавливает ли она обработку полностью?

Также любое исправление для браузера Safari (На самом деле на iPad Safari написано

JS: превышен тайм-аут выполнения

Я предполагаю, что это та же проблема стека вызовов)

Ответы [ 27 ]

533 голосов
/ 23 мая 2011

Это означает, что где-то в вашем коде вы вызываете функцию, которая в свою очередь вызывает другую функцию и т. Д., Пока не достигнете предела стека вызовов.

Это почти всегда из-за рекурсивной функции с базовым случаем, который не выполняется.

Просмотр стека

Рассмотрим этот код ...

(function a() {
    a();
})();

Вот стек после нескольких вызовов ...

Web Inspector

Как видите, стек вызовов увеличивается, пока не достигнет предела: размер стека в жестком коде браузера или исчерпание памяти.

Чтобы исправить это, убедитесь, что у вашей рекурсивной функции есть базовый случай, который можно встретить ...

(function a(x) {
    // The following condition 
    // is the base case.
    if ( ! x) {
        return;
    }
    a(--x);
})(10);
76 голосов
/ 23 апреля 2012

Иногда это можно получить, если вы случайно импортировали / внедрили один и тот же файл JavaScript дважды, и стоит проверить это на вкладке ресурсов инспектора.

38 голосов
/ 14 августа 2016

В моем случае я отправлял элементы ввода вместо их значений:

$.post( '',{ registerName: $('#registerName') } )

Вместо:

$.post( '',{ registerName: $('#registerName').val() } )

Это заморозило мою вкладку Chrome до такой степени, что ее не былодаже показать мне диалоговое окно «Ждать / убить», когда страница перестала отвечать на запросы ...

27 голосов
/ 23 мая 2011

Где-то в вашем коде есть рекурсивный цикл (т. Е. Функция, которая в конечном итоге вызывает себя снова и снова, пока стек не будет заполнен).

Другие браузеры также имеют большие стеки (так что вместо этого вы получаете тайм-аут)или они по какой-то причине проглатывают ошибку (может быть, неправильно размещенный try-catch).

Используйте отладчик для проверки стека вызовов при возникновении ошибки.

11 голосов
/ 24 марта 2017

В моем случае я преобразовывал большой байтовый массив в строку, используя следующее:

String.fromCharCode.apply(null, new Uint16Array(bytes))

bytes содержал несколько миллионов записей, что слишком велико для размещения в стеке.

10 голосов
/ 07 марта 2017

Проблема с определением стековых потоков заключается в том, что иногда трассировка стека раскручивается, и вы не сможете увидеть, что на самом деле происходит.

Я нашел некоторые из более новых инструментов отладки Chrome, полезные для этого.

Нажмите Performance tab, убедитесь, что Javascript samples включены, и вы получите что-то вроде этого.

Совершенно очевидно, где переполнение здесь!Если вы нажмете extendObject, вы сможете увидеть точный номер строки в коде.

enter image description here

Вы также можете увидеть время, которое может или не может быть полезным, или красная сельдь.

enter image description here


Еще один полезный трюк, если вы не можете найти проблему, - это поместить множество операторов console.log там, где вы думаете, что проблема.Предыдущий шаг, описанный выше, может помочь вам в этом.

В Chrome, если вы неоднократно выводите идентичные данные, он будет отображаться так, как показано, где проблема более ясна.В этом случае стек пробил 7152 кадра, прежде чем окончательно рухнул:

enter image description here

6 голосов
/ 16 января 2017

В моем случае событие click распространялось на дочерний элемент. Итак, мне пришлось поставить следующее:

e.stopPropagation ()

при событии клика:

 $(document).on("click", ".remove-discount-button", function (e) {
           e.stopPropagation();
           //some code
        });
 $(document).on("click", ".current-code", function () {
     $('.remove-discount-button').trigger("click");
 });

Вот HTML-код:

 <div class="current-code">                                      
      <input type="submit" name="removediscountcouponcode" value="
title="Remove" class="remove-discount-button">
   </div>
5 голосов
/ 15 ноября 2012

Если по какой-то причине вам нужен бесконечный процесс / рекурсия, вы можете использовать веб-работника в отдельном потоке.http://www.html5rocks.com/en/tutorials/workers/basics/

если вы хотите манипулировать элементами dom и перерисовывать, используйте анимацию http://creativejs.com/resources/requestanimationframe/

5 голосов
/ 28 мая 2012

Проверьте подробности ошибки в консоли панели инструментов Chrome dev, это даст вам функции в стеке вызовов и проведет вас к рекурсии, которая вызывает ошибку.

2 голосов
/ 29 декабря 2016

В моем случае два мода jQuery показывали друг над другом.Предотвращение, которое решило мою проблему.

...