2015-11-25 25 views
5

我想在瀏覽器擴展中使用Fetch API下載資源並計算其哈希值。下面的工作(使用crypto通過Browserify獲取資源,計算哈希,返回承諾

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'); 
    }; 
}) 

,但有一個缺點,我不得不等待a.onloadend而在這我想嵌入的背景下,需要將返回Promise。此外,首先讀取整個blob,然後將其讀入FileReader,然後將其轉儲到createHash似乎很奇怪。

任何提示?

+0

也許這個問題會更適合HTTP: //codereview.stackexchange.com? – Pavlo

+0

這個問題看起來很適合[Code Review.SE](http://codereview.stackexchange.com/),前提條件是(a)你希望檢查代碼的每個方面,而不僅僅是一些, (b)你的代碼已經在工作_(c)你正在要求檢查_concrete,真正的code_,而不是抽象的設計(不管它是否被表示爲代碼)。如果您同意所有這些內容,請閱讀[主題內容](http://codereview.stackexchange.com/help/on-topic),如果您的問題符合要求,請在此處將其刪除並重新發布到CR 。 – Phrancis

+0

(a)和(c)在這裏不適用,所以我想這不適合。 –

回答

2

來解決crypto hash.update method也需要一個緩衝區,所以不需要通過FileReader繞道。只要做到

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'); 
}) 

如果不工作,你可以easily promisify一個FileReader

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

,並使用它像這樣:

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

在第一個代碼塊中,爲什麼第二個'.then()'處理程序中的同步代碼甚至在第二個'.then()'處理程序中?爲什麼它不在第一個'.then()'處理程序中,沒有第二個'.then()'處理程序? – jfriend00

+0

@ jfriend00:'arrayBuffer()'返回一個承諾 – Bergi

+0

第一個塊實際上工作。非常感謝! –

2

我想你在這裏要求的是承諾鏈接。您可以在then處理程序中創建一個承諾並將其返回。

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')); 
     }; 
    }); 
}) 

然後yaypromise可能是您正在尋找的承諾。它將通過hash.digest('hex')

+0

請僅在最低級別進行promisify。將呼叫置於承諾回調中的'crypto'。並且不要忘記附加一個錯誤處理程序。 – Bergi