2015-10-23 7 views
6

Continuo a ricevere un errore ETIMEDOUT o ECONNRESET seguito da un errore Callback was already called quando eseguo index.js.Async.js - ETIMEDOUT e Callback erano già chiamati

In un primo momento ho pensato che fosse perché non ho incluso return prima di chiamare il callback onEachLimitItem. Quindi l'ho incluso per lo async multiple callbacks documentation. Ancora non risolvendolo. Ho anche provato a rimuovere l'evento di errore ea rimuovere il callback su onEachLimit nell'evento di errore, ma nessuno dei due ha funzionato. Ho esaminato le altre domande SO relative al problema di Callback already called, ma poiché non riguardano i flussi, non ho trovato una soluzione.

La mia comprensione è che se lo stream incontra un errore come ECONNRESET, restituirà la richiamata nell'evento di errore e passerà allo stream successivo, ma questo non sembra essere il caso. Sembra quasi che l'errore si risolva da solo, ovvero si riconnette e prova a inviare di nuovo il vapore errato ad Azure e funziona, quindi attiva l'evento "Fine" e otteniamo il Callback already called.

Sto gestendo correttamente le callback negli eventi stream?

var Q = require('q'); 
var async = require('async'); 
var webshot = require('webshot'); 
var Readable = require('stream').Readable; 
var azure = require('azure-storage'); 

var blob = azure.createBlobService('123', '112244'); 
var container = 'awesome'; 

var countries = [ 
    'en-us', 'es-us', 'en-au', 'de-at', 'pt-br', 'en-ca', 'fr-ca', 'cs-cz', 'ar-ly', 'es-ve', 
    'da-dk', 'fi-fi', 'de-de', 'hu-hu', 'ko-kr', 'es-xl', 'en-my', 'nl-nl', 'en-nz', 'nb-no', 
    'nn-no', 'pl-pl', 'ro-ro', 'ru-ru', 'ca-es', 'es-es', 'eu-es', 'gl-es', 'en-gb', 'es-ar', 
    'nl-be', 'bg-bg', 'es-cl', 'zh-cn', 'es-co', 'es-cr', 'es-ec', 'et-ee', 'fr-fr', 'el-gr', 
    'zh-hk', 'en-in', 'id-id', 'en-ie', 'he-il', 'it-it', 'ja-jp', 'es-mx', 'es-pe', 'en-ph' 
]; 

var uploadStreamToStorage = function (fileName, stream, onEachLimitItem) { 
    var readable = new Readable().wrap(stream); 
    var writeable = blob.createWriteStreamToBlockBlob(container, fileName); 

    readable.pipe(writeable); 

    writeable.on('error', function (error) { 
     return onEachLimitItem.call(error); 
    }); 

    writeable.on('finish', function() { 
     onEachLimitItem.call(null); 
    }); 
}; 

var takeIndividualScreenshot = function (ID, country, onEachLimitItem) { 
    var fileName = ID + '-' + country + '.jpg'; 
    var url = 'https://example.com/' + country + '/' + ID; 

    webshot(url, function (error, stream) { 
     if (error) { throw 'Screenshot not taken'; } 

     uploadStreamToStorage(fileName, stream, onEachLimitItem); 

    }); 
}; 

var getAllCountriesOfId = function (ID) { 
    var deferred = Q.defer(); 
    var limit = 5; 

    function onEachCountry(country, onEachLimitItem) { 
     takeIndividualScreenshot(ID, country, onEachLimitItem); 
    } 

    async.eachLimit(countries, limit, onEachCountry, function (error) { 
     if (error) { deferred.reject(error); } 
     deferred.resolve(); 
    }); 

    return deferred.promise; 
}; 

var createContainer = function() { 
    var df = Q.defer(); 
    var self = this; 

    blob.createContainerIfNotExists(this.container, this.containerOptions, function (error) { 

     if (error) { df.reject(error); } 

     df.resolve(self.container); 
    }); 

    return df.promise; 
}; 

createContainer() 
    .then(function() { 
     return getAllCountriesOfId('211007'); 
    }) 
    .then(function() { 
     return getAllCountriesOfId('123456'); 
    }) 
    .fail(function (error) { 
     log.info(error); 
    }); 

enter image description here

+0

Una cosa sto notando è che quando ho eseguito questo sul mio VM (3 GB di RAM) vs localmente (8 GB di RAM), è che lo script continua a gettare l'errore 'ECONNRESET' quando eseguilo sulla mia VM. – Blexy

risposta

4

State lasciando il callback vengono chiamati due volte, come già sapete. La domanda è; vuoi fermarti su tutti gli errori mentre stai iterando lo stream o vuoi accumulare tutti gli errori dallo stream?

Esistono diversi modi per rilevare e gestire gli errori che si stanno già facendo, ma poiché non si genera l'errore oggetto che porta a ulteriori chiamate dal flusso di dati a errore fatale.

L'effettivo problema nel codice è dovuto all'ambito del reso. Quando si gestisce l'errore e si tenta di restituire la richiamata e interrompere l'esecuzione dello script, l'ambito dell'ora di ritorno è locale per il gestore degli errori degli stream, non lo script globale, quindi lo script continua e si attiva passando al successivo flusso valido.

writeable.on('error', function (error) { 
    // This 'return' is in the local scope of 'writable.on('error')' 
    return onEachLimitItem.call(error); 
}); 

Si potrebbe forse impostare un array, quindi gestire l'errore di fuori di tale Funzioni oscilloscopio locale. Ad esempio

// Set the array's scope as global to the writable.on() error 
var errResults = []; 
writeable.on('error', function (error) { 
    // Push the local scoped 'error' into the global scoped 'errResults' array 
    errResults.push(error); 
}); 

writeable.on('finish', function() { 
    // Are there any errors? 
    return (errResults.length > 0) ? 
    onEachLimitItem.call(errors) : onEachLimitItem.call(null); 
}); 

Quanto sopra è solo un modo per affrontare il problema.

Non sono sicuro di aver letto la guida alla gestione degli errori fornita da Joyent (supporti originali del linguaggio node.js) ma dovrebbe darvi un'idea delle opzioni disponibili quando si gestiscono gli errori.

https://www.joyent.com/developers/node/design/errors

+0

Ciao @ jas-, sto usando il listener di errore Qf di 'Q', ma ho appena inviato l'errore al logger che sto usando (l'ho aggiunto allo script sopra). Mi piacerebbe accumulare tutti gli errori dallo stream e non avere lo script crollare - non sono sicuro di come farlo. Leggendo il link Joyent ora. – Blexy

+0

Non ho familiarità con Q, ma come ho detto il tuo script non si ferma sugli errori e viene chiamato due volte. Ciò può verificarsi (ed è nel tuo caso) a causa dell'ambito con cui stai restituendo il gestore degli errori di callback è locale alla funzione di gestione degli errori 'writeable.on()'. –

+0

Potrebbe fornire un esempio di come gestirò l'errore? Grazie, questo è tutto nuovo per me. – Blexy

Problemi correlati