Re: [streams] How will ReadableByteStream work with seekable resources? (#253)

I think I see.

OK, I think what we need to make this more concrete now is a series of use cases that we want to write sample code for.

Here is what I have off the top of my head. Please give me more :).

- (all) Want to read a 10 MiB file into a single ArrayBuffer
- (chunkwise) Want to read a 10 MiB file, 1 MiB at a time, re-using a single 1 MiB ArrayBuffer
- (ping-pong) Want to read a 10 MiB file, 1 MiB at a time, re-using two separate 1 MiB ArrayBuffers (e.g. because you are asynchronously processing the 1 MiB chunks and want to get a potential 1 MiB headstart in parallel with the async processing)

Here is my sample code for setAllocator, let me know if I got this right

```js
// Common prelude
const rbs = getReadableByteStreamForFile("/path/to/file.flac");
const ONE_MIB = 1024 * 1024;
const TEN_MIB = 10 * ONE_MIB;
```

```js
// (all)
const ab = new ArrayBuffer(TEN_MIB);

// This begins the fread(ab, 0, ab.byteLength) call
rbs.setAllocator({
  allocate() { return ab; }
});

// fulfills when the fread() call finishes
rbs.ready.then(() => {
  const readValue = rbs.read();
  assert(readValue === ab);
  console.log("done!", ab);

  // stream is now closed
});
```

```js
// (chunkwise)
const ab = new ArrayBuffer(ONE_MIB);

// This begins the fread(ab, 0, ab.byteLength) call
rbs.setAllocator({
  allocate() { return ab; }
});

// fulfills when the first fread(ab, 0, ONE_MIB) call finishes
rbs.ready.then(() => {
  const readChunk1 = rbs.read();
  assert(readChunk1 === ab);
  console.log("first chunk", ab);

  // queue is now empty but we're not done, so stream automatically kicks off
  // fread(ab, ONE_MIB, ONE_MIB). This next rbs.ready will fulfill when that finishes

  rbs.ready.then(() => {
    const readChunk2 = rbs.read();
    assert(readChunk2 === readChunk1); // as desired; re-using the same buffer
    console.log("second chunk", ab);

    // Etc., until chunk 10, at which point the stream is closed.
    // Recursion left as an exercise for the reader.
  });
});
```

```js
// (ping-pong)
const abs = [new ArrayBuffer(ONE_MIB), new ArrayBuffer(ONE_MIB)];
const counter = 0;

// This begins the fread(abs[0], 0, abs[0].byteLength) call
rbs.setAllocator({
  allocate() {
    return abs[counter++ % 2];
  }
});

// fulfills when the first fread(abs[0], 0, abs[0].byteLength) call finishes
rbs.ready.then(() => {
  const readChunk1 = rbs.read();
  assert(readChunk1 === abs[0]);
  console.log("first chunk", readChunk1);

  // after the rbs.read() call, the stream's queue is now empty but we're not
  // done, so stream automatically kicks off fread(abs[1], ONE_MIB, ONE_MIB).
  // This next rbs.ready will fulfill when that finishes

  Promise.all([
    processChunkAsync(readChunk1),
    rbs.ready
  ])
  .then(() => {
    const readChunk2 = rbs.read();
    assert(readChunk2 === abs[1]); // as desired
    console.log("second chunk", readChunk2);

    // Note that after calling rbs.read() this second time the stream is doing
    // fread(abs[0], 2 * ONE_MIB, ONE_MIB), so abs[0] === readChunk1 is starting
    // to be reused.

    // Anyway, keep going until chunk 10, abstract into recursive function, etc.
  });
});
```

Notably I didn't use your free hook for the (ping-pong) case, so maybe I'm missing something?

---
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/issues/253#issuecomment-73929164

Received on Wednesday, 11 February 2015 17:55:36 UTC