it-swarm.com.ru

Ошибка превышения максимального размера стека вызовов

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

Это говорит 

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

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

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

JS: превышено время ожидания выполнения

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

404
testndtv

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

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

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

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

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

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

Web Inspector

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

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

(function a(x) {
    // The following condition 
    // is the base case.
    if ( ! x) {
        return;
    }
    a(--x);
})(10);
494
alex

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

73
lucygenik

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

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

Вместо:

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

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

34
FKasa

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

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

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

25
Aaron Digulla

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

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

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

11
Nate Glenn

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

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

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

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

 enter image description here

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

 enter image description here


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

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

 enter image description here

9
Simon_Weaver

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

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

5
Dr. Dama

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

5
chim

В моем случае событие 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
Shahdat

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

2
Barry Guvenkaya

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

export default class DateUtils {
  static now = (): Date => {
    return DateUtils.now()
  }
}
0
onmyway133

Почти каждый ответ здесь утверждает, что это может быть вызвано только бесконечным циклом. Это неправда, в противном случае вы могли бы перегрузить стек через глубоко вложенные вызовы (не говоря уже о том, что это эффективно, но, безусловно, это возможно). Если у вас есть контроль над вашей виртуальной машиной JavaScript, вы можете настроить размер стека. Например:

node --stack-size=2000

Смотрите также: Как я могу увеличить максимальный размер стека вызовов в Node.js

0
ghayes

Если вы работаете с Google Maps, то проверьте, передаются ли последние символы в new google.maps.LatLng. В моем случае они передавались как неопределенные. 

0
User-8017771

У меня была эта ошибка, потому что у меня было две функции JS с одинаковым именем

0
iceDragon

вы можете найти свою рекурсивную функцию в браузере Chrome, нажмите Ctrl + Shift + J, а затем вкладку исходного кода, которая дает вам процесс компиляции кода, и вы можете найти, используя точку останова в коде.

0
Vishal Patel

Я тоже сталкивался с подобной проблемой вот в деталях при загрузке логотипа с помощью выпадающего меню загрузки логотипа

<div>
      <div class="uploader greyLogoBox" id="uploader" flex="64" onclick="$('#filePhoto').click()">
        <img id="imageBox" src="{{ $ctrl.companyLogoUrl }}" alt=""/>
        <input type="file" name="userprofile_picture"  id="filePhoto" ngf-select="$ctrl.createUploadLogoRequest()"/>
        <md-icon ng-if="!$ctrl.isLogoPresent" class="upload-icon" md-font-set="material-icons">cloud_upload</md-icon>
        <div ng-if="!$ctrl.isLogoPresent" class="text">Drag and drop a file here, or click to upload</div>
      </div>
      <script type="text/javascript">
          var imageLoader = document.getElementById('filePhoto');
          imageLoader.addEventListener('change', handleImage, false);

          function handleImage(e) {
              var reader = new FileReader();
              reader.onload = function (event) {

                  $('.uploader img').attr('src',event.target.result);
              }
              reader.readAsDataURL(e.target.files[0]);
          }
      </script>
      </div>

CSS.css

.uploader {
  position:relative;
  overflow:hidden;
  height:100px;
  max-width: 75%;
  margin: auto;
  text-align: center;

  img{
    max-width: 464px;
    max-height: 100px;
    z-index:1;
    border:none;
  }

  .drag-drop-zone {
    background: rgba(0, 0, 0, 0.04);
    border: 1px solid rgba(0, 0, 0, 0.12);
    padding: 32px;
  }
}

.uploader img{
  max-width: 464px;
  max-height: 100px;
  z-index:1;
  border:none;
}



.greyLogoBox {
  width: 100%;
  background: #EBEBEB;
  border: 1px solid #D7D7D7;
  text-align: center;
  height: 100px;
  padding-top: 22px;
  box-sizing: border-box;
}


#filePhoto{
  position:absolute;
  width:464px;
  height:100px;
  left:0;
  top:0;
  z-index:2;
  opacity:0;
  cursor:pointer;
}

до исправления мой код был:

function handleImage(e) {
              var reader = new FileReader();
              reader.onload = function (event) {
                  onclick="$('#filePhoto').click()"
                  $('.uploader img').attr('src',event.target.result);
              }
              reader.readAsDataURL(e.target.files[0]);
          }

Ошибка в консоли: 

 enter image description here

Я решил это, удалив onclick="$('#filePhoto').click()" из тега div.

0
spacedev

Оба вызова идентичного кода ниже, если его уменьшить на 1, работают в Chrome 32 на моем компьютере, например. 17905 против 17904. При запуске как есть они выдают ошибку «RangeError: Превышен максимальный размер стека вызовов». Похоже, что этот предел не является жестко заданным, но зависит от аппаратного обеспечения вашей машины. Похоже, что если он вызывается как функция, то этот добровольный предел выше, чем если бы он вызывался как метод, т. Е. Этот конкретный код использует меньше памяти при вызове как функция.

Вызывается как метод:

var ninja = {
    chirp: function(n) {
        return n > 1 ? ninja.chirp(n-1) + "-chirp" : "chirp";
    }
};

ninja.chirp(17905);

Вызывается как функция:

function chirp(n) {
    return n > 1 ? chirp( n - 1 ) + "-chirp" : "chirp";
}

chirp(20889);
0
Elijah Lynn

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

const routes: Routes = [
  {
    path: '',
    component: HomeComponent,
    children: [
      { path: '', redirectTo: 'home', pathMatch: 'prefix' },
      { path: 'home', loadChildren: './home.module#HomeModule' },
    ]
  }
];

Поэтому мне пришлось убрать линию детского маршрута

const routes: Routes = [
  {
    path: '',
    component: HomeComponent,
    children: [
      { path: 'home', loadChildren: './home.module#HomeModule' },
    ]
  }
];
0
Amine Harbaoui

Недавно мы добавили поле на сайт администратора, над которым мы работаем - contact_type ... easy right? Что ж, если вы вызываете select "type" и пытаетесь отправить его через вызов jquery ajax, это завершится неудачно с этой ошибкой, скрытой глубоко в jquery.js. Не делайте этого:

$.ajax({
    dataType: "json",
    type: "POST",
    url: "/some_function.php",
    data: { contact_uid:contact_uid, type:type }
});

Проблема в том, что type: type - я считаю, что мы называем аргумент «type» - наличие значения переменной с именем type не является проблемой. Мы изменили это на:

$.ajax({
    dataType: "json",
    type: "POST",
    url: "/some_function.php",
    data: { contact_uid:contact_uid, contact_type:type }
});

И переписал some_function.php соответственно - проблема решена.

0
Scott

в моем случае я получаю эту ошибку при вызове ajax, и данные, которые я пытался передать этой переменной, не определены, то есть показывает эту ошибку, но не описывает эту переменную, не определенную. Я добавил определил, что переменная n получила значение.

0
asifaftab87

Я знаю, что эта ветка старая, но я думаю, что стоит упомянуть сценарий, в котором я нашел эту проблему, чтобы она могла помочь другим.

Предположим, у вас есть такие вложенные элементы:

<a href="#" id="profile-avatar-picker">
    <span class="fa fa-camera fa-2x"></span>
    <input id="avatar-file" name="avatar-file" type="file" style="display: none;" />
</a>

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

Так что этот код не удастся:

$('#profile-avatar-picker').on('click', (e) => {
    e.preventDefault();

    $('#profilePictureFile').trigger("click");
});

У вас есть два варианта, чтобы избежать этого:

  • Переместите ребенка наружу от родителя.
  • Применить stopPropagation функцию к дочернему элементу.
0
Weslley Ramos

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

    jQuery.ajax({
    url : '/search-result',
    data : {
      searchField : searchField,
      searchFieldValue : searchField,
      nid    :  nid,
      indexName : indexName,
      indexType : indexType
    },
.....
0
Tajdar Khan Afridi