2016-01-09 72 views
0

所以,我想運行一個intervaled功能時,但有一個遞歸超時:避免堆棧溢出運行遞歸超時

var runUpdater = function() { 
    setTimeout(() => { 
    console.log('something here') 
    runUpdater() 
    }, 1000) 
} 

這將體現在將始終爲長期服務運行時間。我認爲這最終會出現堆棧溢出,對嗎?我的問題是:避免它的最好方法是什麼?

+0

代碼中沒有遞歸 - >「問題」解決:) – Andreas

+1

'setInterval()'怎麼樣? – ne1410s

回答

1

不,不會有堆棧溢出。每次調用setTimeout都會在事件循環中排隊一條新消息。當執行setTimeout回調函數時,你會得到一個全新的堆棧,深度爲1,當執行線程完成時它將不再存在。例如,下面將迅速拋出達到最大堆棧大小時,引發RangeError:

try { 
 
    !function func () { 
 
     func(); 
 
    }(); 
 
} catch (e) { 
 
    document.body.innerHTML = e.message; 
 
}

但這個版本不會有任何問題無限期地運行:

try { 
 
    !function func () { 
 
     setTimeout(func, 0); 
 
    }(); 
 
} catch (e) { 
 
    document.body.innerHTML = e.message; 
 
}

1

經過一些測試後,我認爲您的當前代碼沒有遞歸。由於runUpdater()在執行內部runUpdater()後立即退出。 setTimeout()調用並不會阻止瀏覽器的主線程,而是當瀏覽器空閒時安排您的函數調用,然後立即退出(隨後終止調用者,因此不會發生遞歸)

我寧願使用setInterval()你的情況爲可讀性的原因,避免recursive調用任何混亂:(!感謝)的基礎上通過@Paulpro作出評論

setInterval(function() { 
    console.log('something here'); 
}, 1000); 

編輯:

我認爲setInterval確實與相同與延遲和調用相同的功能,但它並沒有,setTimeout的運行順序,當你的函數調用runUpdater()setInterval只是時間表忽略了功能的狀態被稱爲

TL只安排下一次調用; DR:使用他的版本的答案

+0

請注意,如果setInterval運行的代碼比運行它(甚至是異步)之間的延遲時間更長,將會導致問題,因爲它將繼續排隊越來越多的回調並進一步落後。如果每次都發出Ajax請求,那可能會非常糟糕。您可以很容易地達到您的瀏覽器一次發送的最大請求數,然後在其上建立一個大隊列,並且如果您在別處發送任何其他Ajax請求,他們將不會長時間發送。 – Paulpro

+0

@Paulpro指出,謝謝。 –