nodejs超出最大的调用栈错误问题


Posted in NodeJs onDecember 27, 2017

今天早上老大和我说之前项目里面的那个数据要改动,要对 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超出最大的调用栈错误问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

NodeJs 相关文章推荐
用nodejs实现PHP的print_r函数代码
Mar 14 NodeJs
Nodejs进程管理模块forever详解
Jun 01 NodeJs
nodejs中实现sleep功能实例
Mar 24 NodeJs
nodeJs爬虫获取数据简单实现代码
Mar 29 NodeJs
nodejs 的 session 简单使用
Jun 06 NodeJs
nodejs+websocket实时聊天系统改进版
May 18 NodeJs
Nodejs之TCP服务端与客户端聊天程序详解
Jul 07 NodeJs
NodeJs实现定时任务的示例代码
Dec 05 NodeJs
nodejs+mongodb+vue前后台配置ueditor的示例代码
Jan 02 NodeJs
nodejs使用http模块发送get与post请求的方法示例
Jan 08 NodeJs
NodeJS实现自定义流的方法
Aug 01 NodeJs
使用nodeJS中的fs模块对文件及目录进行读写,删除,追加,等操作详解
Feb 06 NodeJs
nodejs实现简单的gulp打包
Dec 21 #NodeJs
nodejs调取微信收货地址的方法
Dec 20 #NodeJs
基于nodejs实现微信支付功能
Dec 20 #NodeJs
nodeJS微信分享
Dec 20 #NodeJs
NodeJS爬虫实例之糗事百科
Dec 14 #NodeJs
nodejs实现爬取网站图片功能
Dec 14 #NodeJs
NodeJs form-data格式传输文件的方法
Dec 13 #NodeJs
You might like
php mssql 分页SQL语句优化 持续影响
2009/04/26 PHP
PHP的博客ping服务代码
2012/02/04 PHP
基于PHP实现栈数据结构和括号匹配算法示例
2017/08/10 PHP
JavaScript 图像动画的小demo
2012/05/23 Javascript
Json和Jsonp理论实例代码详解
2013/11/15 Javascript
JS应用正则表达式转换大小写示例
2014/09/18 Javascript
jQuery中siblings()方法用法实例
2015/01/08 Javascript
在JavaScript中操作时间之getYear()方法的使用教程
2015/06/11 Javascript
jQuery使用模式窗口实现在主页面和子页面中互相传值的方法
2016/03/01 Javascript
Jquery获取第一个子元素简单实例
2016/06/02 Javascript
jQuery实现简单的滑动导航代码(移动端)
2017/05/22 jQuery
vue页面跳转后返回原页面初始位置方法
2018/02/11 Javascript
微信小程序中实现手指缩放图片的示例代码
2018/03/13 Javascript
Vue异步组件处理路由组件加载状态的解决方案
2018/09/07 Javascript
[03:01]2014DOTA2国际邀请赛 小组赛7月13日TOPPLAY
2014/07/14 DOTA
[47:35]VP vs Pain 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/20 DOTA
[02:49:21]2019完美盛典全程录像
2019/12/08 DOTA
Django中实现一个高性能计数器(Counter)实例
2014/07/09 Python
浅谈配置OpenCV3 + Python3的简易方法(macOS)
2018/04/02 Python
tensorflow使用神经网络实现mnist分类
2018/09/08 Python
Python 用matplotlib画以时间日期为x轴的图像
2019/08/06 Python
Python 3.8正式发布重要新功能一览
2019/10/17 Python
Python 中@property的用法详解
2020/01/15 Python
Python正则表达式学习小例子
2020/03/03 Python
Python configparser模块操作代码实例
2020/06/08 Python
Python如何读取、写入CSV数据
2020/07/28 Python
详解pytorch tensor和ndarray转换相关总结
2020/09/03 Python
html5的websockets全双工通信详解学习示例
2014/02/26 HTML / CSS
简述Linux文件系统通过i节点把文件的逻辑结构和物理结构转换的工作过程
2016/01/06 面试题
印刷工程专业应届生求职信
2013/09/29 职场文书
运动会闭幕式解说词
2014/02/21 职场文书
高三高考决心书
2014/03/11 职场文书
租车协议书范本2014
2014/11/17 职场文书
什么是求职信?求职信应包含哪些内容?
2019/08/14 职场文书
MySQL 不等于的三种使用及区别
2021/06/03 MySQL
SQL Server #{}可以防止SQL注入
2022/05/11 SQL Server