Reputation:
What is the difference between:
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);
}
And why should we manually destroy the stream if some error happen? Node won't automatically do that?
Thanks.
Upvotes: 4
Views: 1138
Reputation: 17168
Well for one thing your second example doesn't perform any piping or transfer of data at all. The only other significant difference between the two is that in the first example you're not attaching an 'error' event listener to the read stream which means that if an error occurs while reading the data you won't catch the error. You shouldn't need to remove the "close" listener or destroy the stream. It looks like you're trying to copy a file to a new location and have the function return a Promise. In which case it won't matter if the 'close' event did fire because a Promise can only be resolved/rejected once. So if the 'error' event does fire then your Promise will be rejected and it can never become resolved so there is no reason to remove the 'close' listener. Additionally node will automatically mark the stream as destroyed after it emits an error. This should be all you need:
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)
})
}
Then you can use it as such:
copy('/foo/bar.json', '/baz/qux.json')
.then(() => console.log('copy done'))
Upvotes: 7