Node.js-超出最大调用堆栈大小 [英] Node.js - Maximum call stack size exceeded

查看:255
本文介绍了Node.js-超出最大调用堆栈大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我运行我的代码时,Node.js抛出一个"RangeError: Maximum call stack size exceeded"异常,该异常是由过多的递归调用引起的.我试图通过sudo node --stack-size=16000 app增加Node.js堆栈大小,但是Node.js崩溃而没有任何错误消息.当我不使用sudo再次运行它时,Node.js将显示'Segmentation fault: 11'.是否有可能在不删除递归调用的情况下解决此问题?

When I run my code, Node.js throws a "RangeError: Maximum call stack size exceeded" exception caused by too many recursive calls. I tried to increase Node.js stack size by sudo node --stack-size=16000 app, but Node.js crashes without any error message. When I run this again without sudo, then Node.js prints 'Segmentation fault: 11'. Is there a possibility to solve this without removing my recursive calls?

推荐答案

您应将递归函数调用包装到

You should wrap your recursive function call into a

  • setTimeout
  • setImmediate
  • process.nextTick
  • setTimeout,
  • setImmediate or
  • process.nextTick

函数使node.js有机会清除堆栈.如果您不这样做,并且有很多循环没有任何 real 异步函数调用,或者如果您不等待回调,则RangeError: Maximum call stack size exceeded将是不可避免的.

function to give node.js the chance to clear the stack. If you don't do that and there are many loops without any real async function call or if you do not wait for the callback, your RangeError: Maximum call stack size exceeded will be inevitable.

关于潜在异步循环"的文章很多. 这里是一个.

There are many articles concerning "Potential Async Loop". Here is one.

现在更多示例代码:

// ANTI-PATTERN
// THIS WILL CRASH

var condition = false, // potential means "maybe never"
    max = 1000000;

function potAsyncLoop( i, resume ) {
    if( i < max ) {
        if( condition ) { 
            someAsyncFunc( function( err, result ) { 
                potAsyncLoop( i+1, callback );
            });
        } else {
            // this will crash after some rounds with
            // "stack exceed", because control is never given back
            // to the browser 
            // -> no GC and browser "dead" ... "VERY BAD"
            potAsyncLoop( i+1, resume ); 
        }
    } else {
        resume();
    }
}
potAsyncLoop( 0, function() {
    // code after the loop
    ...
});

这是正确的:

var condition = false, // potential means "maybe never"
    max = 1000000;

function potAsyncLoop( i, resume ) {
    if( i < max ) {
        if( condition ) { 
            someAsyncFunc( function( err, result ) { 
                potAsyncLoop( i+1, callback );
            });
        } else {
            // Now the browser gets the chance to clear the stack
            // after every round by getting the control back.
            // Afterwards the loop continues
            setTimeout( function() {
                potAsyncLoop( i+1, resume ); 
            }, 0 );
        }
    } else {
        resume();
    }
}
potAsyncLoop( 0, function() {
    // code after the loop
    ...
});

现在,您的循环可能会变得太慢,因为我们每回合会浪费一点时间(一次浏览器往返).但是您不必每次都调用setTimeout.通常是可以的每千次执行一次.但这可能取决于您的堆栈大小:

Now your loop may become too slow, because we loose a little time (one browser roundtrip) per round. But you do not have to call setTimeout in every round. Normally it is o.k. to do it every 1000th time. But this may differ depending on your stack size:

var condition = false, // potential means "maybe never"
    max = 1000000;

function potAsyncLoop( i, resume ) {
    if( i < max ) {
        if( condition ) { 
            someAsyncFunc( function( err, result ) { 
                potAsyncLoop( i+1, callback );
            });
        } else {
            if( i % 1000 === 0 ) {
                setTimeout( function() {
                    potAsyncLoop( i+1, resume ); 
                }, 0 );
            } else {
                potAsyncLoop( i+1, resume ); 
            }
        }
    } else {
        resume();
    }
}
potAsyncLoop( 0, function() {
    // code after the loop
    ...
});

这篇关于Node.js-超出最大调用堆栈大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆