直接在可写流中管道可读流

时间:2017-03-31 14:07:58

标签: javascript node.js events stream

有什么区别:

const stream = createReadStream(source).pipe(createWriteStream(destination));

stream.on("error", (error) => {
   stream.destroy();
   stream.removeListener("close");
   reject(error);
});
stream.on("close", () => {
  // do something
});

VS

const writable = createWriteStream(destination);
const readable = createReadStream(source);
readable.on("error", onError);
writable.on("error", onError);
function onError(error) {
  readable.destroy();
  writable.destroy();
  writable.removeListener("close", onClose);
  reject(error);
}

如果发生错误,我们为什么要手动销毁流?节点不会自动执行此操作吗?

感谢。

1 个答案:

答案 0 :(得分:6)

嗯,有一件事你的第二个例子根本不进行任何管道或数据传输。两者之间唯一的另一个显着差异是,在第一个示例中,您没有附加错误'读取流的事件监听器意味着如果在读取数据时发生错误,则不会捕获错误。你不应该删除"关闭"监听或摧毁流。看起来您正在尝试将文件复制到新位置并让该函数返回Promise。在这种情况下,关闭'关闭'事件发生了火灾,因为Promise只能被解决/拒绝一次。所以如果错误'事件确实会触发,然后您的承诺将被拒绝,并且永远无法解决,因此没有理由删除“关闭”。监听器。此外,节点会在发出错误后自动将流标记为已销毁。这应该是你所需要的:

const fs = require('fs')

function copy (source, target) {
  return new Promise((resolve, reject) => {
    const rs = fs.createReadStream(source)
    const ws = fs.createWriteStream(target)
    rs.on('error', reject)
    ws.on('error', reject)
    rs.pipe(ws).on('close', resolve)
  })
}

然后你可以这样使用它:

copy('/foo/bar.json', '/baz/qux.json')
  .then(() => console.log('copy done'))