【问题标题】:NodeJS - Hash a file stream using promisesNodeJS - 使用 Promise 散列文件流
【发布时间】:2017-05-03 13:20:04
【问题描述】:

我现在有一个处理统计和哈希(可能很大)文件的过程。现在我正在这样做:

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...

但我实际上并不明白在这里做什么,而且 Bluebird 网站似乎缺乏细节。

我觉得像Promise.all 这样的东西可能是正确的,但我只是没有看到任何正确语法的好例子。

我知道我可以编写一个包装函数,在各种条件下返回一个承诺,但我不太明白它在承诺领域是如何工作的。也许是这样的?

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

帮助?

【问题讨论】:

    标签: node.js file stream promise es6-promise


    【解决方案1】:

    你可以像这样将你的函数包装在一个 Promise 中:

    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 模块中的常规函数​​,您可以使用 Bluebird 对其进行 promisify。

    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() 用于当您有多个单独的 Promise 并且您想知道它们何时全部实现时。它接受一组承诺作为它的参数,并返回一个新的主承诺,该承诺将使用一组值解决或拒绝发生的第一个错误。所以,你可以这样做:

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

    【讨论】:

    • 太棒了,谢谢。这将许多松散的结局联系在一起,并帮助承诺“点击”到位。
    • 你可能要小心这里。 hash.update 被阻塞并且会阻止事件循环。我可能会使用 github.com/ronomon/crypto-async 包不这样做。
    • @JTWebMan - 请将您的评论发送给 OP,因为他们选择了加密货币。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    • 2022-10-13
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    相关资源
    最近更新 更多