Whats new for streams in Node 8
There are a couple new things landing in streams in Node 8
First up we have a new standardized method to destroy streams, all streams will now have a standardized .destroy() method. This method takes a single optional argument which is an error object. Calling this method destroys the stream and cleans up any underlying resources, if you pass in an error then that is the equivalent of saying ‘destroy this stream because of this error’ and error events are passed along.
In keeping with other stream methods you can also define a _destroy method on the prototype or pass a function in the in the constructor options under the name ‘destroy’ if you need to define a custom method of destroying something
This function will have 2 things passed to it, an error and a callback. The error may be null. The idea is that you clean up any resources being used by your stream and then call the callback with the passed in error (if it exists) or if you encountered an error trying to destroy stuff, then call it with that one.
The idea is that you usually want to pass the error through to the callback but there may be certain types of errors or certain situations where you need to swallow the error.
These are the default ones:
Since they actually do stuff you need to remember to do the closing yourself if implementing it yourself not a big issue for most of them, but if I was implementing a transform stream I’d probably use super:
though fyi this won’t work:
I’ll leave it as an exercise for the ready to figure out why, but do this instead
Before getting into the new feature lets discuss the .flush method on transform streams and some of it’s shortcomings. First it’s only on transform streams, so it doesn’t help you on readable, writable, or regular duplex streams. Second it’s tied to the readable half of the transform stream, so if you do async stuff inside of it it only prevents the readable half of the transform stream from closing, the writable half will have closed on the next tick after flush was called.
Final on the other hand is defined on writable, so it’s also available on duplex and transform streams, and the writable stream won’t close until you call the callback in final (in a transform stream this also causes the readable side to not close because the readable side always waits for the writable side to end) how to use it is pretty much the same as flush, except also on writable.
Final is really helpful when you have a writable stream that needs to clean up or finish up as it ends. For instance I have a module that streams records into a remote service but batches them up to avoid excessive API calls, final is now a non hacky way to do this as previously I could monkey patch the end method (which I did) or put a transform stream in front of it (which I didn’t do because I wanted the API to be a regular writable stream).
More generally I’d also recommend that you should probably use final instead of flush anywhere you were previously using flush in transform streams. There may be a few specific places where you need flush but if your doing something that esoteric you hopefully know what your doing. You can likely look forward to a debate soon about whether to soft depreciate flush going forward or not.