Максимальный размер стека вызовов превысило ошибка



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



Он говорит:




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




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



также любое исправление Safari браузер (на самом деле на iPad Safari, Он скажет




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




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

739   22  

22 ответов:

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

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

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

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

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

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

Web Inspector

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

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

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

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

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

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

вместо:

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

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

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

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

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

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

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

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

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

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

ударил Performance tab, убедится и вы получите что-то вроде этого.

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

enter image description here

вы также можете увидеть тайминги, которые могут или не могут быть полезны или отвлекающий маневр.

enter image description here


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

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

enter image description here

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

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

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

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

e. stopPropagation ()

on click event:

 $(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>

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

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

оба вызова идентичного кода ниже, если они уменьшены на 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);

вы можете найти свою рекурсивную функцию в браузере crome,нажмите ctrl+shift+j, а затем вкладку source, которая дает вам поток компиляции кода, и вы можете найти с помощью точки останова в коде.

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

<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.

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

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

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

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

<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 функция для дочернего элемента.

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

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

еще один параметр, который вызывает эту ошибку Если вы преобразуете в json с помощью сокета.

export class User {
  constructor(socket: Socket, name: string) { 
     this.socket = socket;
     this.name   = name;
  }

   name   : string;
   socket : Socket;
}

...
let json: string = JSON.stringify(user);

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

иногда это происходит из-за типа данных convert , например, у вас есть объект, который вы рассматриваете как строку.

socket.id в nodejs либо в JS client в качестве примера, не является строкой. чтобы использовать его в качестве строки, вы должны добавить строку слова перед:

String(socket.id);

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

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' },
    ]
  }
];

Comments

    Ничего не найдено.