nodejs超出最大的調(diào)用棧錯(cuò)誤問題
今天早上老大和我說之前項(xiàng)目里面的那個(gè)數(shù)據(jù)要改動(dòng),要對(duì) mongodb 中每條記錄進(jìn)行 update 操作,你寫個(gè)腳本跑一下吧。
然后,我默默的回到電腦前,努力工作的一天又開始了。由于此表數(shù)據(jù)量有點(diǎn)略大,該有一千多萬條記錄。所以考慮使用 mongodb 的 cursor 游標(biāo)來進(jìn)行遍歷修改。
程序?qū)崿F(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); } /* 此處為對(duì)數(shù)據(jù)進(jìn)行update操作 */ // 遞歸調(diào)用modify方法 return modify(cursor); }); }else{ console.log('finished'); } }) } var cursor = collection.find(); modify(cursor);
然后讓它慢慢跑吧,可是一個(gè)令我郁悶的事情發(fā)生了。當(dāng)游標(biāo)跑到接近500萬的時(shí)候,程序崩了,提示Uncaught RangeError: Maximum call stack size exceeded
竟然告訴我爆棧了,什么情況? 哎,排查代碼,開始填坑。發(fā)現(xiàn)我上面遞歸調(diào)用了modify() ,而且遞歸次數(shù)有點(diǎn)小多(1000多萬條記錄的表?。?,可能是函數(shù)不斷的遞歸調(diào)用導(dǎo)致它的調(diào)用棧不斷的增加,然后越來越大,最終就沒有然后了,爆棧了??磥淼媒o個(gè)機(jī)會(huì)讓node進(jìn)行垃圾回收一下,要想讓它有機(jī)會(huì)垃圾回收那就只得終結(jié)一下遞歸啊。使用系統(tǒng)的setTimeout();來跳出遞歸調(diào)用棧吧。
代碼修改如下
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); } /* 此處對(duì)數(shù)據(jù)進(jìn)行update操作 */ // 遞歸調(diào)用modify方法 return setTimeout(function(){ //跳出遞歸調(diào)用棧 modify(cursor); },0); }); }else{ console.log('finished'); } }) } var cursor = collection.find(); modify(cursor);
在跑一下試試。。。。ok,好使了。但是運(yùn)行有點(diǎn)慢啊,因?yàn)槲颐看味甲屗鲞f歸調(diào)用棧了。這樣雖然沒問題但是沒必要,因?yàn)?00多萬才會(huì)出現(xiàn)爆棧呢。加個(gè)計(jì)數(shù)器吧,等調(diào)用棧有點(diǎ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); } /* 此處對(duì)數(shù)據(jù)進(jìn)行update操作 */ // 遞歸調(diào)用modify方法 if(count%10000 === 0) { return setTimeout(function(){ //跳出遞歸調(diào)用棧 modify(cursor); },0); }else{ return modify(cursor); } }); }else{ console.log('finished'); } }) } var cursor = collection.find(); modify(cursor);
總結(jié)
以上所述是小編給大家介紹的nodejs超出最大的調(diào)用棧錯(cuò)誤問題,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
nodejs服務(wù)內(nèi)存泄露排查過程和優(yōu)化方法
在開發(fā)和部署Node.js應(yīng)用程序時(shí),內(nèi)存泄露是一個(gè)常見的挑戰(zhàn),本文將探討如何對(duì)于一個(gè)陌生項(xiàng)目進(jìn)行內(nèi)存排查和優(yōu)化的方法,文章通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11理解nodejs的stream和pipe機(jī)制的原理和實(shí)現(xiàn)
本篇文章主要介紹了理解nodejs的stream和pipe機(jī)制的原理和實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08學(xué)習(xí)使用ExpressJS 4.0中的新Router的用法
ExpressJS 4.0中提出了新的路由Router,提供了路由應(yīng)有的API,本文詳細(xì)的介紹了ExpressJS 4.0中的新Router的用法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-11-11Node升級(jí)后vue項(xiàng)目node-sass報(bào)錯(cuò)問題及解決
這篇文章主要介紹了Node升級(jí)后vue項(xiàng)目node-sass報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03