2015-11-25 15 views
5

Vorrei utilizzare lo Fetch API in un'estensione del browser per scaricare una risorsa e calcolare un suo hash. Le seguenti opere (utilizzando crypto attraverso Browserify)recupero risorse, calcolo dell'hash, ritorno della promessa

fetch(url).then(function(response) { 
    return response.blob(); 
}).then(function(data) { 
    var a = new FileReader(); 
    a.readAsBinaryString(data); 
    a.onloadend = function() { 
    var hash = crypto.createHash(hashType); 
    hash.update(a.result, 'binary'); 
    return hash.digest('hex'); 
    }; 
}) 

ma ha lo svantaggio che devo aspettare per a.onloadend mentre il contesto in cui mi piacerebbe incorporare richiede un Promise da restituire. Inoltre, sembra piuttosto strano recuperare prima l'intero blob, quindi leggerlo in uno FileReader solo per scaricarlo in createHash in seguito.

Eventuali suggerimenti?

+0

Forse questa domanda sarà più adatta per http: //codereview.stackexchange.com? – Pavlo

+0

Questa domanda sembra essere adatta per [Code Review.SE] (http://codereview.stackexchange.com/), a condizione che (a) tu voglia rivedere ogni aspetto del tuo codice, non solo alcuni, (b) il tuo codice è già funzionante_, e (c) stai richiedendo una revisione di _concrete, vero codice_, non di un disegno astratto (indipendentemente dal fatto che sia espresso o meno come codice). Se siete d'accordo con tutti questi, leggete su [cosa c'è in argomento] (http://codereview.stackexchange.com/help/on-topic), e, se la vostra domanda è adatta, cancellatela qui e ripubblicatela su CR . – Phrancis

+0

(a) e (c) non sono applicabili qui, quindi immagino che non sia un adattamento. –

risposta

2

Anche lo crypto hash.update method accetta un buffer, quindi non è necessario effettuare una deviazione tramite FileReader. Basta fare

fetch(url).then(function(response) { 
    return response.arrayBuffer(); 
}).then(function(arrayBuffer) { 
    var buffer = require('buffer')(new Uint8Array(arrayBuffer)); 
    var hash = require('crypto').createHash(hashType); 
    hash.update(buffer, 'binary'); 
    return hash.digest('hex'); 
}) 

Se questo non funziona, è possibile easily promisify un FileReader:

function getResult(reader) { 
    return new Promise(function(resolve, reject) { 
     reader.onload = function() { 
      resolve(this.result); 
     }; 
     reader.onerror = reader.onabort = reject; 
    }); 
} 

e usare in questo modo:

fetch(url).then(function(response) { 
    return response.blob(); 
}).then(function(data) { 
    var a = new FileReader(); 
    a.readAsBinaryString(data); 
    return getResult(a); 
}).then(function(result) { 
    var hash = crypto.createHash(hashType); 
    hash.update(result, 'binary'); 
    return hash.digest('hex'); 
}) 
+0

Nel tuo primo blocco di codice perché il codice sincrono nel secondo gestore '.then()' anche in un secondo handler '.then()? Perché non è solo nel primo handler '.then() senza secondi' .then()? Handler? – jfriend00

+0

@ jfriend00: 'arrayBuffer()' restituisce una promessa – Bergi

+0

Il primo blocco in effetti funziona. Molte grazie! –

2

Penso che quello che stai chiedendo qui è la promessa di concatenare. È possibile creare una promessa all'interno del gestore then e restituirla.

var yaypromise = fetch(url).then(function(response) { 
    return response.blob(); 
}).then(function(data) { 
    return new Promise(function(resolve, reject){ 
     var a = new FileReader(); 
     a.readAsBinaryString(data); 
     a.onloadend = function() { 
     var hash = crypto.createHash(hashType); 
     hash.update(a.result, 'binary'); 
     resolve(hash.digest('hex')); 
     }; 
    }); 
}) 

E poi yaypromise è probabilmente la promessa che stai cercando. Si risolverà con hash.digest('hex')

+0

Per favore prometti solo al livello più basso.Metti la chiamata a 'crypto' in un callback di promessa. E non dimenticare di allegare un gestore di errori. – Bergi

Problemi correlati