溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

nodejs超出最大的調用棧錯誤怎么辦

發(fā)布時間:2021-07-13 15:38:28 來源:億速云 閱讀:305 作者:小新 欄目:web開發(fā)

這篇文章將為大家詳細講解有關nodejs超出最大的調用棧錯誤怎么辦,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

我默默的回到電腦前,努力工作的一天又開始了。由于此表數(shù)據量有點略大,該有一千多萬條記錄。所以考慮使用 mongodb 的 cursor 游標來進行遍歷修改。

程序實現(xiàn)的代碼大致如下

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);
     }
     /* 此處為對數(shù)據進行update操作 */
     // 遞歸調用modify方法 
     return modify(cursor);
   }); 
    }else{
      console.log('finished');
    }
  })
}
var cursor = collection.find();
modify(cursor);

然后讓它慢慢跑吧,可是一個令我郁悶的事情發(fā)生了。當游標跑到接近500萬的時候,程序崩了,提示Uncaught RangeError: Maximum call stack size exceeded

竟然告訴我爆棧了,什么情況? 哎,排查代碼,開始填坑。發(fā)現(xiàn)我上面遞歸調用了modify() ,而且遞歸次數(shù)有點小多(1000多萬條記錄的表啊),可能是函數(shù)不斷的遞歸調用導致它的調用棧不斷的增加,然后越來越大,最終就沒有然后了,爆棧了。看來得給個機會讓node進行垃圾回收一下,要想讓它有機會垃圾回收那就只得終結一下遞歸啊。使用系統(tǒng)的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);
        }
        /* 此處對數(shù)據進行update操作 */
        // 遞歸調用modify方法 
        return setTimeout(function(){ 
              //跳出遞歸調用棧
              modify(cursor);
            },0);
      }); 
    }else{
      console.log('finished');
    }
  })
}
var cursor = collection.find();
modify(cursor);

在跑一下試試。。。。ok,好使了。但是運行有點慢啊,因為我每次都讓它跳出遞歸調用棧了。這樣雖然沒問題但是沒必要,因為400多萬才會出現(xiàn)爆棧呢。加個計數(shù)器吧,等調用棧有點大的時候在跳出來。

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);
        }
        /* 此處對數(shù)據進行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超出最大的調用棧錯誤怎么辦”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI