Ошибка: превышен максимальный размер стека вызовов
Я использую библиотеку JavaScript Direct Web Remoting (DWR) и получаю ошибку только в Safari (на настольном компьютере и iPad).
Ошибка выглядит следующим образом:
Maximum call stack size exceeded.
Что именно означает эта ошибка и останавливает ли она выполнение полностью?
Кроме того, есть ли какие-либо решения для браузера Safari? На самом деле, на iPad Safari я получаю сообщение:
JS: execution exceeded timeout
Я предполагаю, что это связано с той же проблемой с переполнением стека вызовов.
5 ответ(ов)
В вашем случае вы отправляли элементы ввода вместо их значений:
$.post('', { registerName: $('#registerName') })
Вместо:
$.post('', { registerName: $('#registerName').val() })
Это привело к зависанию вкладки Chrome, до такой степени, что она даже не показывала диалог 'Ждать/Убить', когда страница стала неотзывчивой...
Вы можете иногда столкнуться с этой проблемой, если случайно импортируете или встраиваете один и тот же JavaScript файл дважды. Рекомендуется проверить это в вкладке "Ресурсы" в инструментах разработчика.
У вас в коде где-то есть рекурсивный цикл (т.е. функция, которая в конечном итоге снова и снова вызывает саму себя, пока стек не заполнится).
Другие браузеры, возможно, имеют больший размер стека (поэтому вместо этого вы получите тайм-аут) или по какой-то причине игнорируют ошибку (возможно, из-за неправильно расположенного блока try-catch).
Используйте отладчик, чтобы проверить стек вызовов, когда возникает ошибка.
В вашем случае вы сталкиваетесь с проблемой переполнения стека при попытке конвертировать большой массив байтов в строку с использованием следующего кода:
String.fromCharCode.apply(null, new Uint16Array(bytes))
Проблема заключается в том, что apply
создает множество аргументов для своей функции, что может привести к переполнению стека, когда вы передаете слишком большое количество элементов, как в вашем случае — несколько миллионов.
Для решения этой проблемы вы можете использовать метод String.fromCharCode
в цикле, разбивая массив на более мелкие части. Например:
let result = '';
const chunkSize = 65536; // Максимальное количество элементов для одной итерации
for (let i = 0; i < bytes.length; i += chunkSize) {
result += String.fromCharCode.apply(null, new Uint16Array(bytes.slice(i, i + chunkSize)));
}
В этом коде мы разбиваем массив bytes
на части размером chunkSize
и конвертируем каждую часть отдельно, избегая переполнения стека. Это должно помочь вам успешно завершить конвертацию, даже если количество байтов очень велико.
В вашем случае событие клика распространялось на дочерний элемент. Поэтому мне пришлось добавить следующее:
e.stopPropagation();
в обработчик события клика:
$(document).on("click", ".remove-discount-button", function (e) {
e.stopPropagation();
// какой-то код
});
$(document).on("click", ".current-code", function () {
$('.remove-discount-button').trigger("click");
});
Вот HTML-код:
<div class="current-code">
<input type="submit" name="removediscountcouponcode" value="Удалить" title="Удалить" class="remove-discount-button">
</div>
Таким образом, с помощью e.stopPropagation()
вы предотвращаете дальнейшую обработку события клика, что может быть полезно, если у вас есть несколько вложенных элементов, реагирующих на один и тот же клик.
Получить координаты (X,Y) HTML-элемента
Прокрутка до низа div?
Потеряно HTML-кодирование при чтении атрибута из поля ввода
jQuery/JavaScript: Замена битых изображений
Несколько файлов JavaScript/CSS: лучшие практики?