[whatwg/streams] Proposal: BodyReader for ReadableStream (Issue #1308)

### What problem are you trying to solve?

It is very common to consume a `ReadableStream` into a text, TypedArray, Blob, etc. In the fetch spec, there is the `Body` structure that exposes methods like `text()`, `json()`, `blob()`, etc for efficiently consuming the `Request` or `Response` payload. Unfortunately, for other types of `ReadableStream`s it's not so efficient and generally requires a fair amount of boilerplate. It would be nice to simplify.

```js
async function text(readable) {
  let text = '';
  const dec = new TextDecoder();
  for await (const chunk of readable) {
    text += dec.decode(chunk, { stream: true });
  }
  text += dec.decode();
  return text;
}
```

### What solutions exist today?

The `Response` and `Request` objects have methods like `async text()`, `async json()`, etc ...

Node.js has a `require('stream/adapters')` API that implements these methods for `ReadableStream` and Node.js streams.

### How would you solve it?

This proposal is to introduce a new `ReadableStreamBodyReader` to the streams spec with the definition. Like `ReaableStreamBYOBReader`, the `ReadableStreamBodyReader` would only be used with `bytes` type streams.

```
[Exposed=*]
interface ReadableStreamBodyReader {
  constructor(ReadableStream);

  Promise<ArrayBuffer> arrayBuffer();
  Promise<Blob> blob();
  Promise<FormData> formData();
  Promise<any> json();
  Promise<USVString> text();

  undefined releaseLock();
};
ReadableStreamBodyReader includes ReadableStreamGenericReader;
```

Example use:
```
const readable = new ReadableStream({ type: 'bytes', /* ... */ });
const reader = new ReadableStreamBodyReader(readable);
// or 
const reader = readable.getReader({ mode: 'body' });
await text = reader.text();

// With decoding...
const source = new ReadableStream({ type: 'bytes', /* ... */ });
const readable = source.pipeThrough(new TextDecoderStream());
const reader = new ReadableStreamBodyReader(readable);
await text = reader.text();
```

This model would allow implementations to optimize the read operation internally as much as possible and eliminate a fair amount of boilerplate.


### Anything else?

_No response_

-- 
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/issues/1308
You are receiving this because you are subscribed to this thread.

Message ID: <whatwg/streams/issues/1308@github.com>

Received on Saturday, 23 March 2024 20:54:54 UTC