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

 更新时间:2017年12月27日 10:56:46   作者:youyu岁月  
这篇文章主要介绍了nodejs超出最大的调用栈错误问题,需要的朋友可以参考下

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

相关文章

  • node使用async_hooks模块进行请求追踪

    node使用async_hooks模块进行请求追踪

    这篇文章主要介绍了node使用async_hooks模块进行请求追踪,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 简单实现node.js图片上传

    简单实现node.js图片上传

    这篇文章主要为大家详细介绍了node.js图片上传的简单实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • NodeJS学习笔记之Connect中间件模块(二)

    NodeJS学习笔记之Connect中间件模块(二)

    本文续上文的内容,介绍下nodejs中connect中间件的使用方式及用途,希望大家喜欢。
    2015-01-01
  • Node.js中多进程模块Cluster的介绍与使用

    Node.js中多进程模块Cluster的介绍与使用

    众所周知Node.js是单线程的,一个单独的Node.js进程无法充分利用多核。Node.js从v0.6.0开始,新增cluster模块,让Node.js开发Web服务时,很方便的做到充分利用多核机器。这篇文章主要给大家介绍了关于Node.js中多进程模块Cluster的相关资料,需要的朋友可以参考下
    2017-05-05
  • Node.js中HTTP模块与事件模块详解

    Node.js中HTTP模块与事件模块详解

    这篇文章主要详细介绍了Node.js中HTTP模块与事件模块的相关资料,需要的朋友可以参考下
    2014-11-11
  • Node.js返回JSONP详解

    Node.js返回JSONP详解

    下面小编就为大家带来一篇Node.js返回JSONP详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-05-05
  • 详解如何在vscode里面调试js和node.js的方法步骤

    详解如何在vscode里面调试js和node.js的方法步骤

    这篇文章主要介绍了详解如何在vscode里面调试js和node.js的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • Express使用multer实现文件上传的示例代码

    Express使用multer实现文件上传的示例代码

    这篇文章主要介绍了Express 使用 multer 实现文件上传的操作步骤,文中通过代码示例和图文结合的方式讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-03-03
  • NodeJs Express路由使用流程解析

    NodeJs Express路由使用流程解析

    路由路径和请求方法一起定义了请求的端点,它可以是字符串、字符串模式或者正则表达式。后端在获取路由后,可通过一系列类似中间件的函数去执行事务
    2023-01-01
  • Nodejs学习笔记之测试驱动

    Nodejs学习笔记之测试驱动

    本文是本系列文章的第二篇,主要是测试针对于web后端的驱动,在开发过程中,在开发完成一段代码后如果负责任而不是说完全把问题交给测试人员去发现的话,这个时候通常都会去做一些手动的测试。
    2015-04-04

最新评论