最大调用堆栈大小超出错误

时间:2011-05-23 09:49:48

标签: javascript html webkit callstack dwr

我正在使用Direct Web Remoting(DWR)JavaScript库文件,仅在Safari(桌面和iPad)中出现错误

它说

  

超出了最大调用堆栈大小。

这个错误究竟是什么意思,它是否会完全停止处理?

Safari浏览器的任何修正(实际上在iPad Safari,它说

  

JS:执行超出超时

我假设是相同的调用堆栈问题)

35 个答案:

答案 0 :(得分:523)

这意味着代码中的某个地方,您正在调用一个函数,该函数又调用另一个函数,依此类推,直到达到调用堆栈限制为止。

这几乎总是因为具有基本案例的递归函数未得到满足。

查看堆栈

考虑这段代码......

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

这是一些电话后的堆栈......

Web Inspector

正如您所看到的,调用堆栈会一直增长,直到达到限制:浏览器硬编码堆栈大小或内存耗尽。

为了解决这个问题,请确保您的递归函数具有能够满足的基本情况......

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

答案 1 :(得分:73)

如果您不小心导入/嵌入相同的JavaScript文件两次,有时可以获得此信息,值得在检查员的资源标签中查看。

答案 2 :(得分:35)

就我而言,我发送输入元素而不是它们的值:

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

而不是:

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

这会冻结我的Chrome标签,以至于当页面无响应时它甚至没有显示“等待/终止”对话框...

答案 3 :(得分:27)

在你的代码中某处有一个递归循环(即一个函数最终会一次又一次地调用自己,直到堆栈已满)。

其他浏览器要么具有更大的堆栈(所以你得到超时),要么因为某些原因吞下错误(也许是一个糟糕的try-catch)。

使用调试器在发生错误时检查调用堆栈。

答案 4 :(得分:11)

就我而言,我使用以下内容将大字节数组转换为字符串:

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

bytes包含数百万个条目,这些条目太大而无法放入堆栈。

答案 5 :(得分:10)

检测堆栈溢出的问题有时是堆栈跟踪将展开,您将无法看到实际发生的情况。

我发现Chrome的一些较新的调试工具对此非常有用。

点击Performance tab,确保Javascript samples已启用,您将获得此类内容。

溢出就在这里很明显!如果您点击extendObject,您将能够在代码中真正看到确切的行号。

enter image description here

您还可以查看可能有用或无用的时间或红鲱鱼。

enter image description here

如果你实际上找不到问题,另一个有用的技巧是在你认为问题所在的位置放置大量的console.log语句。上面的上一步可以帮助您。

在Chrome中,如果您反复输出相同的数据,则会显示相同的数据,以显示问题更清晰的位置。在这种情况下,堆栈在最终崩溃之前达到7152帧:

enter image description here

答案 6 :(得分:6)

就我而言,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>

答案 7 :(得分:5)

如果由于某种原因需要运行无限进程/递归,则可以在单独的线程中使用webworker。 http://www.html5rocks.com/en/tutorials/workers/basics/

如果你想操作dom元素并重绘,请使用动画 http://creativejs.com/resources/requestanimationframe/

答案 8 :(得分:5)

检查Chrome开发工具栏控制台中的错误详细信息,这将为您提供调用堆栈中的函数,并引导您进行导致错误的递归。

答案 9 :(得分:2)

就我而言,两个jQuery模式显示在彼此之上。防止这解决了我的问题。

答案 10 :(得分:1)

对于我作为TypeScript的初学者来说,这是 _var1 的获取者和安装者中的问题。

class Point2{
    
    constructor(private _var1?: number, private y?: number){}

    set var1(num: number){
        this._var1 = num  // problem was here, it was this.var1 = num
    }
    get var1(){
        return this._var1 // this was return this.var1
    }
}

答案 11 :(得分:1)

我们最近在我们正在处理的管理站点中添加了一个字段-contact_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-问题已解决。

答案 12 :(得分:0)

当 MongoDB 数据库的架构与我们创建的模型不匹配时,我在 express/nodejs 应用程序中遇到此错误。

答案 13 :(得分:0)

dtTable.dataTable({
    sDom: "<'row'<'col-sm-6'l><'col-sm-6'f>r>t<'row'<'col-sm-6'i><'col-sm-6'p>>",
    "processing": true,
    "serverSide": true,
    "order": [[6, "desc"]],
    "columnDefs": [
        {className: "text-right", "targets": [2, 3, 4, 5]}
    ],
    "ajax": {
        "url": "/dt",
        "data": function (d) {
            d.loanRef = loanRef;
        }
    },
    "fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
        var editButton = '';
        // The number of columns to display in the datatable
        var cols = 8;
        // Th row element's ID
        var id = aData[(cols - 1)];
    }
});

在上面的 data 函数中,我使用了相同的名称 d.loanRef = loanRef 但没有创建变量 loanRef 因此递归地声明自己。

解决方案:声明一个 loanRef 变量,或者更好,使用与 d.loanRef 上使用的名称不同的名称。

答案 14 :(得分:0)

就我而言,我基本上忘了获得value中的input

错误

let name=document.getElementById('name');
param={"name":name}

正确

let name=document.getElementById('name').value;
param={"name":name}

答案 15 :(得分:0)

我正在使用React-Native 0.61.5 和( npm 6.9.0&节点10.16.1

当我在Project中安装任何新库时,我都拥有

(例如npm install @ react-navigation / native --save)

最大呼叫堆栈大小超出错误

为此,我尝试

sudo npm cache clean --force

(注意:-以下命令通常花费1到2分钟的时间 取决于您的 npm缓存大小)

答案 16 :(得分:0)

在Angular中,如果您使用mat-select并具有400多个选项,则可能会发生此错误 https://github.com/angular/components/issues/12504

您必须更新@ angular / material版本

答案 17 :(得分:0)

就我而言 我错误地给我分配了相同的变量名,并将其分配给val函数“ class_routine_id”

var class_routine_id = $("#class_routine_id").val(class_routine_id);

它应该像:

 var class_routine_id = $("#class_routine_id").val(); 

答案 18 :(得分:0)

遇到了同样的问题,却没想到是什么原因开始怪Babel;)

在浏览器中,代码没有返回任何异常:

if (typeof document.body.onpointerdown !== ('undefined' || null)) {

问题被严重创建|| (或)部分作为babel创建自己的类型检查:

function _typeof(obj){if(typeof Symbol==="function"&&_typeof(Symbol.iterator)==="symbol")

因此删除

|| null

使通天塔进行翻译。

答案 19 :(得分:0)

这也可能导致Maximum call stack size exceeded错误:

var items = [];
[].push.apply(items, new Array(1000000)); //Bad

与此处相同:

items.push(...new Array(1000000)); //Bad

来自Mozilla Docs

  

但是要注意:以这种方式使用应用时,您可能会面临超过   JavaScript引擎的参数长度限制。的后果   应用带有过多参数的函数(请考虑数十个   数千个参数)因引擎而异(JavaScriptCore具有   硬编码参数限制为65536),因为该限制(实际上甚至   未明确说明任何过大堆栈行为的性质)。   一些引擎将引发异常。更有害的是,其他人会   任意限制实际传递给   应用功能。为了说明后一种情况:如果是这样的引擎   限制为四个参数(当然,实际限制是   明显更高),就好像参数5、6、2、3具有   已通过以适用于以上示例,而不是完整示例   数组。

所以尝试:

var items = [];
var newItems = new Array(1000000);
for(var i = 0; i < newItems.length; i++){
  items.push(newItems[i]);
}

答案 20 :(得分:0)

几乎每个答案都表明这只能由无限循环引起。事实并非如此,否则您可能会通过深度嵌套的调用来使堆栈超负荷运行(并不是说这很有效,但这肯定在可能的范围内)。如果您可以控制JavaScript VM,则可以调整堆栈大小。例如:

node --stack-size=2000

另请参阅:How can I increase the maximum call stack size in Node.js

答案 21 :(得分:0)

检查您是否具有调用自身的函数。例如

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

答案 22 :(得分:0)

在我的情况下,我在ajax调用中遇到此错误,并且尝试传递该变量的数据尚未定义,这向我显示了此错误,但未描述未定义的变量。我添加了定义,变量n获得了价值。

答案 23 :(得分:0)

在我的情况下,问题是因为我的子路由与父路由相同:

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

答案 24 :(得分:0)

如果您正在使用Google地图,请检查传入new google.maps.LatLng的lat lng是否格式正确。在我的情况下,他们被传递为未定义。

答案 25 :(得分:0)

我遇到了这个错误,因为我有两个同名的JS函数

答案 26 :(得分:0)

我知道这个帖子已经老了,但我认为值得一提的是我发现这个问题的方案,所以它可以帮助别人。

假设你有这样的嵌套元素:

<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函数应用于子元素。

答案 27 :(得分:0)

我遇到了同样的问题 我通过删除在ajax上使用两次的字段名称来解决它 e.g

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

答案 28 :(得分:0)

我在这里也面临类似问题的细节  使用下拉徽标上传框上传徽标时

<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

我通过从div标签中删除onclick="$('#filePhoto').click()"来解决它。

答案 29 :(得分:0)

你可以在chrome浏览器中找到你的递归函数,按ctrl + shift + j然后按源选项卡,它会为你提供代码编译流程,你可以在代码中找到使用断点。

答案 30 :(得分:0)

如果在我的计算机上的Chrome 32中减少1个工作,则下面相同代码的两次调用,例如17905 vs 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);

答案 31 :(得分:-1)

我试图在未声明该变量的情况下为其赋值。

声明变量修复了我的错误。

答案 32 :(得分:-1)

有时是由于转换数据类型而发生的,例如,您有一个被视为字符串的对象。

例如,在js客户端中的nodejs中的

socket.id都不是字符串。要将其用作字符串,您必须在前面添加单词String:

String(socket.id);

答案 33 :(得分:-2)

T̶h̶i̶s̶̶c̶a̶n̶̶h̶a̶p̶p̶e̶n̶̶w̶h̶e̶n̶̶y̶o̶u̶̶t̶r̶y̶̶p̶u̶s̶h̶̶a̶n̶̶a̶r̶r̶a̶y̶i̶i̶n̶t̶ let alerts = []; alerts.push(alerts);
编辑-
我错了。谢谢@melpomene的纠正。

我在AWS cloud 9控制台中遇到了错误,并且删除了上面的代码解决了该问题。我将返回代码,找出其修复的真正原因并在此处进行更新。

答案 34 :(得分:-3)

对我有用

$('form')[0].submit()