我正在尝试运行以下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]
我不认为这是你所期望的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