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

4 javascript events stream node.js

有什么区别:

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

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

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);
}
Run Code Online (Sandbox Code Playgroud)

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

谢谢.

idb*_*old 6

好吧,有一点,你的第二个例子根本不执行任何管道或数据传输.两者之间唯一的另一个显着区别是,在第一个示例中,您没有将"错误"事件侦听器附加到读取流,这意味着如果在读取数据时发生错误,则不会捕获错误.您不应该删除"关闭"侦听器或销毁流.看起来您正在尝试将文件复制到新位置并使该函数返回Promise.在这种情况下,"关闭"事件是否触发无关紧要,因为Promise只能被解析/拒绝一次.因此,如果"错误"事件触发,那么您的Promise将被拒绝,并且它永远不会被解析,因此没有理由删除"close"侦听器.此外,节点会在发出错误后自动将流标记为已销毁.这应该是你所需要的:

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)
  })
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样使用它:

copy('/foo/bar.json', '/baz/qux.json')
  .then(() => console.log('copy done'))
Run Code Online (Sandbox Code Playgroud)