[streams] Make .ready fulfill-only? (#245)

Continuing from https://github.com/whatwg/streams/issues/243#issuecomment-62424537:

The essential issue is that right now `rs.ready.then(f, r)` might call `f` at a time when the stream is actually in an errored state, if the underlying source or sink causes an error between becoming readable and `f` being called. So the story is something like "usually if `f` is called it'll be readable or closed, and whenever it's errored it'll call `r` with the error ... except not always."

A few issues, none of them too serious:

### Slightly more awkward for readable streams

I tried to change this and noticed it made one example a bit more awkward:

```js
function streamToConsole(readableStream) {
  pump();

  function pump() {
    while (readableStream.state === "readable") {
      console.log(readableStream.read());
    }

    if (readableStream.state === "closed") {
      console.log("--- all done!");
    } else {
      // If we're in an error state, the returned promise will be rejected with
      // that error, so no need to handle "waiting" vs. "errored" separately.
      readableStream.ready.then(pump, e => console.error(e));
    }
  }
}
```

becomes something like

```js
function streamToConsole(readableStream) {
  readableStream.closed.then(
    () => console.log("--- all done!"),
    e => console.error(e);
  );

  pump();

  function pump() {
    while (readableStream.state === "readable") {
      console.log(readableStream.read());
    }

    if (readableStream.state === "waiting") {
      readableStream.ready.then(pump);
    }

    // otherwise "closed" or "errored", which will be handled above.
  }
}
```

That is, it becomes mandatory to interact with the `.closed` promise now if you want access to the error object. Note that this doesn't work:

```js
function streamToConsole(readableStream) {
  pump();

  function pump() {
    while (readableStream.state === "readable") {
      console.log(readableStream.read());
    }

    if (readableStream.state === "closed") {
      console.log("--- all done!");
    } else if (readableStream.state === "errored") {
      // uh oh how do I get the error object? :(
    } else {
      // must be waiting
      readableStream.ready.then(pump);
    }
  }
}
```

Also note that the first version (i.e. with the current spec) isn't actually buggy, since if `pump` is called when the stream is errored it will just call `.ready.then(pump, logTheError)` again.

### What do we do for writable streams?

Writable streams have basically the same problem. However we reject their `.ready` promise more often, i.e. when the stream begins closing, or is closed. Do we also want to eliminate those cases? My gut instinct is that yes, we do. In fact the current setup is not great.

---

So what do you guys think, @tyoshino and @yutakahirano? Can we live with the change in consumer style? And are we OK making it fulfill-only for writable streams too? I think both are OK but wanted to discuss first.

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

Received on Monday, 24 November 2014 22:57:15 UTC