我正在使用Direct Web Remoting(DWR)JavaScript库文件,我只在Safari(桌面和iPad)中收到错误
它说
超出最大调用堆栈大小 .
这个错误究竟是什么意思,它是否完全停止处理?
也是 Safari 浏览器的任何修复(实际上在 iPad Safari ,它说
Safari
iPad Safari
JS:执行超过了超时
我假设是相同的调用堆栈问题)
这意味着在代码中的某个地方,您正在调用一个函数,该函数又调用另一个函数,依此类推,直到达到调用堆栈限制 .
这几乎总是因为具有未满足的基本情况的递归函数 .
考虑这段代码......
(function a() { a(); })();
这是一些电话后的堆栈......
正如您所看到的,调用堆栈会一直增长,直到达到限制:浏览器硬编码堆栈大小或内存耗尽 .
为了解决这个问题,请确保您的递归函数具有能够满足的基本情况......
(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) .
发生错误时,使用调试器检查调用堆栈 .
检测堆栈溢出的问题有时堆栈跟踪将展开,您将无法看到实际发生的情况 .
我发现Chrome的一些较新的调试工具对此非常有用 .
点击 Performance tab ,确保 Javascript samples 已启用,你会得到类似的东西 .
Performance tab
Javascript samples
这里的溢出很明显!如果单击 extendObject ,您将能够在代码中实际看到确切的行号 .
extendObject
您还可以查看可能有用或无用的时间或红鲱鱼 .
如果你实际上找不到问题,另一个有用的技巧是在你认为问题所在的地方放置很多 console.log 语句 . 上面的上一步可以帮助您 .
console.log
在Chrome中,如果您重复输出相同的数据,它将显示如下,以显示问题更清楚的位置 . 在这种情况下,堆栈在最终崩溃之前达到7152帧:
在我的例子中,我使用以下内容将大字节数组转换为字符串:
String.fromCharCode.apply(null, new Uint16Array(bytes))
bytes 包含数百万个条目,这些条目太大而无法放入堆栈 .
bytes
检查Chrome开发工具栏控制台中的错误详细信息,这将为您提供调用堆栈中的功能,并引导您进行导致错误的递归 .
如果由于某种原因需要运行无限进程/递归,则可以在单独的线程中使用webworker . http://www.html5rocks.com/en/tutorials/workers/basics/
如果你想操纵dom元素并重绘,请使用动画http://creativejs.com/resources/requestanimationframe/
就我而言,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>
在我的例子中,两个jQuery模式显示在彼此之上 . 防止这解决了我的问题 .
在我的情况下,我在ajax调用上得到这个错误,我试图传递该变量的数据没有定义,这显示我这个错误,但没有描述未定义的变量 . 我添加了定义变量n得到的值 .
如果在我的计算机上的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);
你可以找到你的递归函数在crome浏览器中,按ctrl shift j然后按源选项卡,它为您提供代码编译流程,您可以在代码中找到使用断点 .
我还遇到类似的问题,这是使用下拉徽标上传框上传徽标时的详细信息
<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]); }
控制台中的错误:
我通过从div标签中删除 onclick="$('#filePhoto').click()" 来解决它 .
onclick="$('#filePhoto').click()"
我遇到了同样的问题我通过删除在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函数
如果您正在使用谷歌 Map ,那么检查lat lng是否被传递到 new google.maps.LatLng 是否是正确的格式 . 在我的情况下,他们被传递为未定义 .
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);
我在Angular中使用Devexpress Scheduler,问题是不正确地使用分配给调度程序的datasource标记的变量 .
有时因为转换数据类型而发生,例如您有一个被视为字符串的对象 .
例如,在js客户端中的nodejs中的socket.id不是字符串 . 要将它用作字符串,您必须在之前添加单词String:
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' }, ] } ];
当没有声明该变量时,我试图分配一个变量,一个值 .
声明变量修复了我的错误 .
检查您是否有自己调用的函数 . 例如
export default class DateUtils { static now = (): Date => { return DateUtils.now() } }
24 回答
这意味着在代码中的某个地方,您正在调用一个函数,该函数又调用另一个函数,依此类推,直到达到调用堆栈限制 .
这几乎总是因为具有未满足的基本情况的递归函数 .
查看堆栈
考虑这段代码......
这是一些电话后的堆栈......
正如您所看到的,调用堆栈会一直增长,直到达到限制:浏览器硬编码堆栈大小或内存耗尽 .
为了解决这个问题,请确保您的递归函数具有能够满足的基本情况......
如果你不小心导入/嵌入相同的JS文件两次,你有时可以得到这个,值得在检查员的资源选项卡中检查:)
就我而言,我发送输入元素而不是它们的值:
代替:
这冻结了我的Chrome标签,甚至在页面变得无响应时向我显示“等待/终止”对话框...
在代码中的某处有一个递归循环(即最终一次又一次地调用自身直到堆栈已满的函数) .
其他浏览器要么有更大的堆栈(所以你得到超时)或者他们因某种原因吞下错误(可能是一个糟糕的try-catch) .
发生错误时,使用调试器检查调用堆栈 .
检测堆栈溢出的问题有时堆栈跟踪将展开,您将无法看到实际发生的情况 .
我发现Chrome的一些较新的调试工具对此非常有用 .
点击
Performance tab
,确保Javascript samples
已启用,你会得到类似的东西 .这里的溢出很明显!如果单击
extendObject
,您将能够在代码中实际看到确切的行号 .您还可以查看可能有用或无用的时间或红鲱鱼 .
如果你实际上找不到问题,另一个有用的技巧是在你认为问题所在的地方放置很多
console.log
语句 . 上面的上一步可以帮助您 .在Chrome中,如果您重复输出相同的数据,它将显示如下,以显示问题更清楚的位置 . 在这种情况下,堆栈在最终崩溃之前达到7152帧:
在我的例子中,我使用以下内容将大字节数组转换为字符串:
bytes
包含数百万个条目,这些条目太大而无法放入堆栈 .检查Chrome开发工具栏控制台中的错误详细信息,这将为您提供调用堆栈中的功能,并引导您进行导致错误的递归 .
如果由于某种原因需要运行无限进程/递归,则可以在单独的线程中使用webworker . http://www.html5rocks.com/en/tutorials/workers/basics/
如果你想操纵dom元素并重绘,请使用动画http://creativejs.com/resources/requestanimationframe/
就我而言,click事件正在子元素上传播 . 所以,我必须提出以下内容:
点击事件:
这是html代码:
在我的例子中,两个jQuery模式显示在彼此之上 . 防止这解决了我的问题 .
在我的情况下,我在ajax调用上得到这个错误,我试图传递该变量的数据没有定义,这显示我这个错误,但没有描述未定义的变量 . 我添加了定义变量n得到的值 .
如果在我的计算机上的Chrome 32中减少1个工作,则下面两个相同代码的调用,例如17905 vs 17904.如果按原样运行,它们将产生错误“RangeError:超出最大调用堆栈大小” . 似乎这个限制不是硬编码的,而是取决于您机器的硬件 . 看来,如果作为函数调用,则该自赋限制高于作为方法调用的情况,即该特定代码在作为函数调用时使用较少的存储器 .
作为方法调用:
作为函数调用:
你可以找到你的递归函数在crome浏览器中,按ctrl shift j然后按源选项卡,它为您提供代码编译流程,您可以在代码中找到使用断点 .
我还遇到类似的问题,这是使用下拉徽标上传框上传徽标时的详细信息
CSS.css
在更正之前我的代码是:
控制台中的错误:
我通过从div标签中删除
onclick="$('#filePhoto').click()"
来解决它 .我遇到了同样的问题我通过删除在ajax上使用两次的字段名称来解决它,例如
我知道这个线程已经过时了,但我认为值得一提的是这个场景我发现了这个问题所以它可以帮助别人 .
假设你有这样的嵌套元素:
您无法在其父事件内操纵子元素事件,因为它会传播到自身,进行递归调用直到抛出异常 .
所以这段代码会失败:
您有两种方法可以避免这种情况:
将孩子移到父母的外面 .
将stopPropagation函数应用于子元素 .
我有这个错误,因为我有两个同名的JS函数
如果您正在使用谷歌 Map ,那么检查lat lng是否被传递到
new google.maps.LatLng
是否是正确的格式 . 在我的情况下,他们被传递为未定义 .导致此错误的另一个选项如果使用套接字转换为json .
我在Angular中使用Devexpress Scheduler,问题是不正确地使用分配给调度程序的datasource标记的变量 .
有时因为转换数据类型而发生,例如您有一个被视为字符串的对象 .
例如,在js客户端中的nodejs中的socket.id不是字符串 . 要将它用作字符串,您必须在之前添加单词String:
在我的情况下的问题是因为我有子路径与父母路径相同:
所以我不得不删除儿童路线
当没有声明该变量时,我试图分配一个变量,一个值 .
声明变量修复了我的错误 .
检查您是否有自己调用的函数 . 例如