提问者:小点点

Javascript堆内存不足错误


我正在尝试运行以下while循环,但由于某些原因,我遇到了一个JS堆内存不足错误:

 while( typeof(apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p]) == 'undefined') {
    //create time delay of one second
    setTimeout(function(){
        //put code to run after delay here
        if( typeof(apiResults[0].league.season.eventType[0].events[0].pbp[i+1].pbpDetails[0]) != 'undefined') {
            //this will run if the next inning has come through
            i = i+1;
            p = 0;
        }
            //this will also pass the while loop and go down to the actual code
    }, 3000);
}

我知道逻辑是有缺陷的,但现在我只在if语句为真的情况下运行它。

我收到以下错误:

11450 ms:标记-扫描1388.5 (1433.0)-

<--- JS stacktrace --->
Cannot get stack trace in GC.
FATAL ERROR: MarkCompactCollector: semi-space copy, fallback in old gen Allocation failed - JavaScript heap out of memory
 1: node::Abort() [/usr/local/bin/node]
 2: node::FatalException(v8::Isolate*, v8::Local<v8::Value>, v8::Local<v8::Message>) [/usr/local/bin/node]

共3个答案

匿名用户

我不认为这是你所期望的setTimeout接受您传递的函数,并在延迟之后,将该函数添加到堆栈中,然后再添加其他所有内容。由于while循环阻塞,最终会出现一种奇怪的情况,即延迟函数在while循环完成之前不会被调用。

var x = 0;
while (x<10) {
  x++;
  console.log('omg');
  setTimeout(function(){console.log('from timeout');},0);
}

匿名用户

如果i=i1是代码中唯一更改i的地方,这可能解释了这一点。您的代码将不断重复并为setTimeout创建数千次计时器,因为i只能在3秒后更改(这将推进循环)(假设计时器不会因创建的所有计时器的加载而延迟,很可能会延迟)。

您需要重构此代码,以避免在循环中使用setTimeout

匿名用户

根据KarlReid的回答(很好的解释),你可能想试试这个:

var i=0;
while( typeof(apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p]) == 'undefined' && i<=apiResults[0].league.season.eventType[0].events[0].pbp.length) {
setTimeout(function(i){//notice the bound i...

    if( typeof(apiResults[0].league.season.eventType[0].events[0].pbp[i+1].pbpDetails[0]) != 'undefined') {
        //some code
    }

}, 3000,i);
i = i+1;//increase in the main loop
}

或递归(一个接一个超时):

(function loop(i){
    if( typeof(apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p]) == 'undefined' && i<=apiResults[0].league.season.eventType[0].events[0].pbp.length) {
        setTimeout(function(i){//notice the bound i...

             if( typeof(apiResults[0].league.season.eventType[0].events[0].pbp[i+1].pbpDetails[0]) != 'undefined') {
                 //some code
             }
             //next
            loop(i+1);
         }, 3000,i);
    }
})(0);//start with zero