nodejs超出最大的調(diào)用棧錯(cuò)誤問題
今天早上老大和我說之前項(xiàng)目里面的那個(gè)數(shù)據(jù)要改動(dòng),要對 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);
}
/* 此處為對數(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)用棧不斷的增加,然后越來越大,最終就沒有然后了,爆棧了。看來得給個(gè)機(jī)會讓node進(jìn)行垃圾回收一下,要想讓它有機(jī)會垃圾回收那就只得終結(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);
}
/* 此處對數(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多萬才會出現(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);
}
/* 此處對數(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ò)誤問題,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
node使用async_hooks模塊進(jìn)行請求追蹤
這篇文章主要介紹了node使用async_hooks模塊進(jìn)行請求追蹤,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
NodeJS學(xué)習(xí)筆記之Connect中間件模塊(二)
本文續(xù)上文的內(nèi)容,介紹下nodejs中connect中間件的使用方式及用途,希望大家喜歡。2015-01-01
Node.js中多進(jìn)程模塊Cluster的介紹與使用
眾所周知Node.js是單線程的,一個(gè)單獨(dú)的Node.js進(jìn)程無法充分利用多核。Node.js從v0.6.0開始,新增cluster模塊,讓Node.js開發(fā)Web服務(wù)時(shí),很方便的做到充分利用多核機(jī)器。這篇文章主要給大家介紹了關(guān)于Node.js中多進(jìn)程模塊Cluster的相關(guān)資料,需要的朋友可以參考下2017-05-05
詳解如何在vscode里面調(diào)試js和node.js的方法步驟
這篇文章主要介紹了詳解如何在vscode里面調(diào)試js和node.js的方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12
Express使用multer實(shí)現(xiàn)文件上傳的示例代碼
這篇文章主要介紹了Express 使用 multer 實(shí)現(xiàn)文件上傳的操作步驟,文中通過代碼示例和圖文結(jié)合的方式講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-03-03
Nodejs學(xué)習(xí)筆記之測試驅(qū)動(dòng)
本文是本系列文章的第二篇,主要是測試針對于web后端的驅(qū)動(dòng),在開發(fā)過程中,在開發(fā)完成一段代碼后如果負(fù)責(zé)任而不是說完全把問題交給測試人員去發(fā)現(xiàn)的話,這個(gè)時(shí)候通常都會去做一些手動(dòng)的測試。2015-04-04

