2014-11-22 8 views
6

cercare aiuto da guru di nodejs là fuori sull'uso delle promesse. Ho il seguente programma di test, in cui invoco una funzione "q" asincrona che lancia semplicemente un'eccezione. Questo programma perde memoria in modo consistente; ma la perdita scompare se si esclude la chiamata .done().Nodejs - promesse, interruzione non gestita e perdita di memoria

Perché la perdita si verifica quando la promessa non viene terminata (vale a dire nessuna chiamata fatta)? Ho provato a seguire lo documentation, ma ho difficoltà a capire la spiegazione del metodo done(). Grazie in anticipo per il vostro aiuto!

Ecco il mio codice:

(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

Come è stato determinato che si verifichi una perdita di memoria? Inoltre, sono solo curioso, per qualsiasi ragione tu stia avvolgendo tutto questo in una funzione anonima? –

+0

@torazaburo - la chiamata console.log che stampa l'utilizzo della memoria segnala l'utilizzo di mem piuttosto costante con la chiamata .done(), ma cresce costantemente quando commento out .done(). Funzione Anon - questa è generata dal compilatore di script caffè, che genera questo stile di codice per le variabili dell'ambito in modo corretto, protegge dai conflitti di nomi globali ecc. – PKK

+0

@torazaburo - Questo non dovrebbe essere un problema perché la funzione di test viene eseguita tramite setImmediate() chiamata. – PKK

risposta

5

Rispondendo alla mia domanda, speriamo che aiutare qualcuno.

Scavando un po 'nel codice della libreria q, sembra che tutte le eccezioni non gestite vengano inserite in un array denominato unhandledRejections, per impostazione predefinita. Non sono sicuro del motivo per cui è stato implementato in questo modo, ma presumibilmente per aiutare gli sviluppatori a rintracciare le eccezioni non gestite. Questo comportamento può essere modificato chiamando Q.stopUnhandledRejectionTracking(). Quando l'ho fatto, la perdita di memoria è andata via, anche senza la chiamata .done().

+1

L'array 'unhandledRejections' sembra essere a scopo di test unitario: https://github.com/kriskowal/q/issues/265 – PKK