Reading Streams in the Browser

One of the more interesting features of the Web that I haven’t had an opportunity to use much yet is streams. A stream is a sequence of data processed over time. Usually, what happens is that the data is broken into pieces, then each chunk is processed, either written or read. In the Web, working with streams is done through the Stream API, which provides ReadableStream and WritableStream interfaces to read and write streams, respectively. The interface for ReadableStream is pretty easy to grok, while WritableStream is a bit harder to follow. As such, I’ll only be covering ReadableStream in this article. To be fair, most of the time you’ll probably be reading streams more than writing them.

ReadableStream

1
2
3
const response = await fetch('example.com')
const reader = response.body.getReader()
const { value, done } = reader.read()

The ReadableStream interface is used when you want to read a stream. In our example, the body property of a Response returns a ReadableStream To use it, you must first get a reader from the ReadableStream instance. This is done by calling ReadableStream.getReader(), which returns a reader of the ReadableStream. Once you have a reader from a ReadableStream, only that reader can read from the ReadableStream. Then you must call the read method of the reader to get a value of the form { value: chunk, done: boolean }. The value is the chunk read by the reader. done represents whether the stream has been closed or not. Thus, to read all the chunks of a stream, you can use a while loop until done is set to true. Since ReadableStream is an async iterator, you can also use a for await...of loop to process each chunk.