我正在计算一些繁重的递归函数(假设下面的代码是斐波那契的)我有两个版本:-第一个,普通递归(不注释"if(n%5==0)“)-第二个,每5个调用使用一次process.nextTick,以便让其他代码运行(不注释"if(false)”)
现在运行第一个得到一个"RangeError:超出了最大调用堆栈大小“,而运行第二个得到一个很好的"196418”。
这是代码。你能告诉我发生了什么吗,因为我不敢相信process.nextTick正在清理堆栈。
'use strict';
function fibo_cb( n, cb ){ fibo_rec( n, (res) => cb( res ) ); }
function fibo_rec( n, ret ){
if( n<2 ){
ret( 1 );
} else {
let rr = (res_1) => { return (res_2) => ret(res_1+res_2) };
let r = (res_1) => fibo_rec( n-2, rr(res_1) );
//if(false){ //no tick
if(n%5==0){ //do tick, once every 5
process.nextTick( () => fibo_rec( n-1, r ) );
} else {
fibo_rec( n-1, r );
}
}
}
fibo_cb( 26, console.log );
发布于 2019-10-18 18:40:28
通过在函数级别创建作用域,将所有代码放入调用堆栈来执行JavaScript代码。因为JavaScript是单线程的(异步任务除外),所以从全局开始,每个作用域都被逐个放入调用堆栈,直到它到达所有函数。一旦函数完成,它就会从调用堆栈中弹出。
在递归函数的情况下,对于每个递归调用,都会将一个函数推送到call Stack。因此,当有大量递归调用时,调用堆栈会变满,因为调用堆栈的最大限制是固定的。
任何使用process.nextTick
调度的异步任务都会等待,直到调用堆栈为空,并从事件队列中获取每个回调,并将其推送到调用堆栈。这会重复发生,直到所有的递归回调都完成。
由于每次未观察到"RangeError:超出最大调用堆栈大小“时,调用堆栈都会清空。
https://stackoverflow.com/questions/58448561
复制相似问题