2014-11-22 33 views
6

尋求nodejs專家對使用承諾的幫助。我有以下測試程序,其中我調用異步「q」函數,只是拋出一個異常。這個程序相當一致地泄漏內存;但如果取消註釋.done()調用,泄漏消失。Nodejs - 承諾,未處理的終止和內存泄漏

爲什麼泄漏發生在承諾未終止時(即沒有完成()調用)?我試圖遵循documentation,但無法理解done()方法的解釋。在此先感謝您的幫助!

這裏是我的代碼:

(function() { 
    var MAX_ITER_COUNT, Q, iterCount, maxMem, noop, qDoit, test; 

    Q = require("q"); 

    iterCount = 0; 

    MAX_ITER_COUNT = 10 * 1000; 

    maxMem = 0; 

    noop = function() {}; 

    qDoit = function() { 
    var currentMem; 
    currentMem = Math.round(process.memoryUsage().heapUsed/1024/1024); 
    if (currentMem > maxMem) { 
     maxMem = currentMem; 
    } 
    console.log("" + iterCount + " - memory is: " + currentMem + "/" + maxMem + " MB"); 
    return Q(10).then(function() { 
     throw new Error("X"); 
    }); 
    }; 

    test = function() { 
    if (iterCount++ > MAX_ITER_COUNT) { 
     console.log("DONE"); 
     return; 
    } 

    // ---- If I uncomment the done() call below the leak goes away ---- 
    return qDoit()["finally"](function() { 
     return setImmediate(test); 
    }) 
    //.done(noop, noop, noop); 


    }; 

    Q.onerror = function() {}; 

    test(); 

}).call(this); 
+0

您是如何確定發生內存泄漏的?也只是好奇,任何理由你把這整個事情包裝在一個匿名函數中? – 2014-11-22 18:18:17

+0

@torazaburo - 打印內存使用情況報告的console.log調用使用.done()調用非常不變的內存使用情況,但在註釋掉.done()時一直增長。匿名函數 - 這是由咖啡腳本編譯器生成的,它產生這種風格的代碼來正確地爲變量作用域,避免全局名稱衝突等。 – PKK 2014-11-22 18:28:20

+0

@torazaburo - 這應該不是問題,因爲測試函數是通過setImmediate()呼叫。 – PKK 2014-11-22 19:10:56

回答

5

回答我的問題,希望這將幫助別人。

在挖掘一下q庫代碼後,它看起來像所有未處理的異常都放在一個名爲unhandledRejections的數組中,默認情況下。不知道爲什麼它是這樣實現的,但大概是爲了幫助開發人員追蹤未處理的異常。通過調用Q.stopUnhandledRejectionTracking()可以更改此行爲。當我這樣做時,即使沒有撥打.done(),內存泄漏也會消失。

+1

未處理的拒絕數組似乎是用於單元測試的目的:https://github.com/kriskowal/q/issues/265 – PKK 2014-11-24 19:21:23