视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
nodejs超出最大的调用栈错误问题
2020-11-27 22:22:39 责编:小采
文档

今天早上老大和我说之前项目里面的那个数据要改动,要对 mongodb 中每条记录进行 update 操作,你写个脚本跑一下吧。

然后,我默默的回到电脑前,努力工作的一天又开始了。由于此表数据量有点略大,该有一千多万条记录。所以考虑使用 mongodb 的 cursor 游标来进行遍历修改。

程序实现的代码大致如下

function modify(cursor) {
 cursor.hasNext(function(err,bool) {
 if(err) {
 return console.log(err); 
 } 
 if(bool) {
 cursor.next(function(err, item){
 if(err) {
 return console.log(err);
 }
 /* 此处为对数据进行update操作 */
 // 递归调用modify方法 
 return modify(cursor);
 }); 
 }else{
 console.log('finished');
 }
 })
}
var cursor = collection.find();
modify(cursor);

然后让它慢慢跑吧,可是一个令我郁闷的事情发生了。当游标跑到接近500万的时候,程序崩了,提示Uncaught RangeError: Maximum call stack size exceeded

竟然告诉我爆栈了,什么情况? 哎,排查代码,开始填坑。发现我上面递归调用了modify() ,而且递归次数有点小多(1000多万条记录的表啊),可能是函数不断的递归调用导致它的调用栈不断的增加,然后越来越大,最终就没有然后了,爆栈了。看来得给个机会让node进行垃圾回收一下,要想让它有机会垃圾回收那就只得终结一下递归啊。使用系统的setTimeout();来跳出递归调用栈吧。

代码修改如下

function modify(cursor) { 
 cursor.hasNext(function(err,bool) {
 if(err) {
 return console.log(err); 
 }
 if(bool) { 
 cursor.next(function(err, item){
 if(err) {
 return console.log(err);
 }
 /* 此处对数据进行update操作 */
 // 递归调用modify方法 
 return setTimeout(function(){ 
 //跳出递归调用栈
 modify(cursor);
 },0);
 }); 
 }else{
 console.log('finished');
 }
 })
}
var cursor = collection.find();
modify(cursor);

在跑一下试试。。ok,好使了。但是运行有点慢啊,因为我每次都让它跳出递归调用栈了。这样虽然没问题但是没必要,因为400多万才会出现爆栈呢。加个计数器吧,等调用栈有点大的时候在跳出来。

var count = 0;
function modify(cursor) { 
 count++;
 cursor.hasNext(function(err,bool) {
 if(err) {
 return console.log(err); 
 }
 if(bool) {
 cursor.next(function(err, item){
 if(err) {
 return console.log(err);
 }
 /* 此处对数据进行update操作 */
 // 递归调用modify方法 
 if(count%10000 === 0) {
 return setTimeout(function(){ 
 //跳出递归调用栈
 modify(cursor);
 },0);
 }else{
 return modify(cursor);
 } 
 }); 
 }else{
 console.log('finished');
 }
 })
}
var cursor = collection.find();
modify(cursor);

总结

以上所述是小编给大家介绍的nodejs超出最大的调用栈错误问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

下载本文
显示全文
专题