如何处理大型对象并避免内存不足错误?

时间:2015-10-05 20:14:42

标签: javascript node.js mongoose

我正在尝试处理一个大型数组,但该对象有时会很大,以至于它会破坏服务器:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory

我可以通过node --max-old-space-size=100然后运行我的进程在本地重现这个。没有设置此选项,它可以正常工作。

这是代码中断的部分

function setManagers(json){
return Q.all(json.map(function(obj){
    return getUserByUsername(obj.username)
    .then(function(user){
        console.log('got here'); //never hits
        ...
function getUserByUsername(username){
    console.log('getting user'); //hits
    return UserModel.findOneQ({username:username})
    .then(function(user){
        console.log('search finished'); //never hits
        if(user){
            console.log('got user');
            return Q(user);
        }else{
            console.log('no user');
            return Q.reject({message:'user ' + username + ' could not be found locally'});
        }
    });
}

我认为这个问题是由于它是一个巨大的数组,其长度超过5000

如果我要删除限制内存的选项,或者使用较小的数据集,那就可以了。

有没有简单的方法可以避免此错误?

1 个答案:

答案 0 :(得分:0)

问题是你同时进行了太多的数据库调用。

我会更改你的逻辑,向数据库发送一个排序字符串,其中所有用户名都用逗号连接,我会立即得到所有用户。然后,我会遍历这些用户,并对您从数据库中收到的用户做任何事情。

另一个不会突破当前逻辑的解决方案是逐个执行数据库操作,例如,使用promise-while:

function pwhile(condition, body) {
  var done = Q.defer();

  function loop() {
    if (!condition())
      return done.resolve();
    Q.when(body(), loop, done.reject);
  }

  Q.nextTick(loop);

  return done.promise;
}

function setManagers(json) {
  var i = 0;
  return pwhile(function() { i < json.length; }, function() {
    var p = getUserByUsername(json[i].username);
    i++;
    return p;
  });
}