2016-12-18 91 views
0

我已經有一個過程,即統計和哈希(可能很大)的文件。現在我這樣做:NodeJS - 使用承諾哈希文件流

function gen_hash (fn, callback) { 
    var hash = crypto.createHash('sha256'); 

    var fh = fs.createReadStream(fn); 
    fh.on('data', d => hash.update(d)); 
    fh.on('end',() => { 
    var digest = hash.digest('hex'); 
    }); 
} 

function gen_stat (fn, callback) { 
    fs.stat(fn, function (err, stats) { 
    if (err) { 
     if (err.code == "ENOENT") { 
     file.exists = false; 
     } 
    } 
    } 
} 

然後我有一些代碼,當他們都完成時允許回調。正如你可以想象的那樣,這很公平......參與。

我認爲這是Promises的一個很好的匹配,但我不知道如何使用它們。

我嘗試了一些東西,如:

const Promises = require('bluebird'); 
const fs = Promises.promisifyAll(require('fs')); 

fh = fs.createReadStream(fn) 
.then... 
.error... 

但我不真正瞭解這裏做什麼,和藍鳥網站似乎缺乏細節。

我覺得像Promise.all這樣的東西可能是正確的,但我沒有看到任何正確語法的好例子。

我明白我可以編寫一個封裝函數,它可以在各種條件下返回一個promise,但我並不完全知道它是如何在promise-land中起作用的。也許這樣?

const fs = Promise.promisifyAll(require('fs')); 

function promise_checksum (fn) { 
    return new Promise((fulfill, reject) => { 
    // What goes here...? 
    } 
} 

function promise_stat (fn) { 
    return new Promise((fulfill, reject) => { 
    fs.stat(fn).then((err, stats) => { 
     if (err) { 
     reject(err); 
     } else { 
     fulfill(stats); 
     } 
    } 
    } 
} 

function checksum_and_stat (fn) { 
    return new PromiseAll((fulfill, reject) => { 
    // What goes here? 
    }); 
} 

幫助?

回答

1

你可以用你的功能在這樣一個承諾:

function gen_hash (fn) { 
    return new Promise((resolve, reject) => { 
     var hash = crypto.createHash('sha256'); 
     var fh = fs.createReadStream(fn); 

     fh.on('data', d => hash.update(d)); 
     fh.on('end',() => { 
      var digest = hash.digest('hex'); 
      resolve(digest); 
     }); 
     fh.on('error', reject); 
    }); 
} 

用法示例:

gen_hash(someFileName).then(hash => { 
    console.log("hash is: ", hash); 
}).catch(err => { 
    console.err(err); 
}); 

對於常規功能Node.js的fs模塊,你可以使用藍鳥以促成它們。

const Promise = require('bluebird'); 
const fs = Promise.promisifyAll(require('fs')); 

這將創建fs對象上的帶有Async端(除了常規的那些是標準fs模塊的一部分)和新方法,而不是接受的回調,這些新的方法將返回一個諾言。 Bluebird將會提供這些方法中的每一種,並提供自己的回調來管理您的承諾。這裏有一個例子:

fs.statAsync(someFileName).then(stats => { 
    console.log(stats); 
}).catch(err => { 
    console.err(err); 
}); 

Promise.all()當你有多個獨立的承諾,你想知道什麼時候它們都滿足使用。它接受一組承諾,因爲它是參數,它返回一個新的主承諾,該承諾將用出現的第一個錯誤的值或拒絕數組來解決。所以,你可以這樣做:

function checksum_and_stat (fn) { 
    return Promise.all([gen_hash(fn), fs.statAsync(fn)]); 
} 

checksum_and_stat(someFileName).then(args => { 
    console.log("hash: ", args[0]); 
    console.log("stats: ", args[1]); 
}).catch(err => { 
    console.err(err); 
}); 
+0

太棒了,謝謝。這將很多鬆散的目標聯繫在一起,並幫助承諾'點擊'到位。 –

+0

你可能想在這裏小心。 hash.update被阻塞並且會阻塞事件循環。我可能會使用https://github.com/ronomon/crypto-async包來不這樣做。 – JTWebMan

+0

@JTWebMan - 請將您的評論引導至OP,因爲加密的選擇是他們的。 – jfriend00