直接在可写stream中pipe道可读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); } 

为什么我们应该手动销毁stream如果发生错误? 节点不会自动做到这一点?

谢谢。

一件事你的第二个例子根本不执行任何pipe道或数据传输。 两者之间唯一的另一个显着差异是,在第一个示例中,您没有将“错误”事件侦听器附加到读取stream,这意味着如果在读取数据时发生错误,您将无法捕获错误。 您不需要删除“closures”侦听器或破坏stream。 它看起来像你试图复制一个文件到一个新的位置,并让该函数返回一个Promise。 在这种情况下,“closures”事件是否因为只能解决/拒绝一次Promise而触发并不重要。 所以,如果“错误”事件触发,那么你的承诺将被拒绝,它永远不会被解决,所以没有理由去除“closures”侦听器。 此外,节点会在发出错误后自动将stream标记为已销毁。 这应该是你需要的一切:

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