-
Notifications
You must be signed in to change notification settings - Fork 163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ReadableStream.getReader name is a bit misleading #308
Comments
I think conceptually the stream can only have one reader at a time. The stream is locked by getReader(), so if you try to call it again you get an exception. Given those semantics, I think "get" is a bit better than "create". Naming is hard, though. |
Yeah, @wanderview covered my point of view pretty nicely. Even though it does get a new one each time it's (successfully) called, "conceptually" only one "real" reader exists per stream. The mapping of that conceptual reader to JS objects is not one-to-one though. |
From a dev point of view, getReader is really 'lock the stream and get me I would really avoid using getXXX in case one can never get the same JS The single-reader is a nice meta-model but I doubt users will actually have
|
I mean, suggestions welcome. I don't think it's unprecedented for |
What about acquireLock?
|
Why is acquire better than get? It just seems like a fancy synony that takes longer to type and spell. |
I agree we should use some better name if possible that implies:
But I don't come up with anything that is as short and simple as "getReader". |
In gecko we use |
"take" also sounds good to me |
+1 2015-04-01 6:02 GMT+02:00 Takeshi Yoshino notifications@github.com:
|
I definitely don't think takeReader makes sense. At this point I think we need evidence that other getX() methods on the web platform return the same object each time. My suspicion is the opposite---that getReader() is already consistent with the platform. |
Indeed. Here are other methods that follow the getX() pattern and return a new object every time:
And that's just going through some IDL files... The most clear-cut analogous examples are getAsFile, getCueAsHTML, and getImageData/getImageDataHD. There are indeed a few instances where the same object could be returned, e.g. getAttribute or getElementById. But there's definitely no consensus. In general, when something is supposed to be stable over time, a getter is used (node.ownerDocument, not node.getOwnerDocument()). Does this allay your concerns, @youennf? |
These examples look all good as getters. Calling getReader changes the state of the stream in observal ways: calling Acquire, take or any other similar name give a hint that you should take 2015-04-01 15:12 GMT+02:00 Domenic Denicola notifications@github.com:
|
Domenic, could you explain the reason why you think (wanna hear it though I'm fine with |
taking something to me means that it's already there, and you're taking it from someone else who has it. That's not really what's going on, or even how it should be conceptualized. I would put takeReader on some class that gets a reader, holds it, but might want to let others have it for a while while it's not using it. Also my objection to acquire is that it's basically synonymous with "get", at least how I hear the two words used in my life. ("Go acquire me a coffee" is just a more formal/sillier way of saying "go get me a coffee".) It doesn't really imply exclusive access in my experience. So I don't understand @youennf's arguments that "get a reader" feels safe/idempotent whereas "acquire a reader" does not. I think at one point we called it |
Thanks. Updated the list. |
What does the reader abstraction give you that couldn't be done via a change in semantics of the read method? In other words, why not just stream.read() ? What else can you call on the reader? |
@domenic Thanks for the context! Intuitively, I would have thought that one would construct a reader and compose in a stream that the reader would operate on. i.e. : const reader = new StreamReader(stream);
reader.read(); // the reader would do something like stream.lock() and stream.release() internally
Just read this:
Which makes my comment a moot point.... 😄 |
Yeah, if you manage to get a In any case, thanks for your attention to the spec! |
It seems like instead of checking the current landscape for APIs that return the same thing or not when calling Any other APIs that we can only call once (even for a time)? |
It feels like |
@SlexAxton Agreed. Along those lines, it would feel natural for read() to throw when calling it on a stream (if it were there vs the reader) the second time.....back to the difficulty in naming this thing. |
What about "access" as in: const reader = stream.accessReader(); It seems to convey some level of exclusivity (you can only 'access' this under certain conditions). |
I don't find Alternatively, it could be more like the APIs that require user permissions, in that the access can be blocked: stream.requestReader(function(err, reader) {}); But then it gets all async and weird, but "request" feels more right. |
stream.secureReader();
stream.reserveReader(); |
👍 for "request" |
|
const reader = stream.viaReader(); ....since really the intent seems to be that you are 'proxying' access to the stream via the reader object. |
There seems to be some confusion. You can get another reader if you release the original one first. |
....which seems to somewhat fit into: const reader = stream.reserveReader();
reader.release();
const reader2 = stream.reserveReader(); // ok
const reader3 = stream.reserveReader(); // throw... reader wasn't released. |
I don't think throwing an error is unsound for getX methods. XMLHttpRequest.responseText can throw an error, for example (I mean, methods are more likely to throw errors than attribute getters). |
Per my habit, I will reason by analogy to established patterns from which to project names. What happens between when you release a reader and get/acquire/take/retain a new one? I am going to assume for the sake of argument that the stream’s buffer accumulates and no information is lost. I suspect that Stream and Reader correspond to the same conceptual entity, so there’s API funny-business going on. Stream and Reader both correspond to sources of data that can have only one consumer (unicast). They differ in that the Stream provides no opinions about how to consume it and alternately vends out to a Reader and instead guarantees that it will only vend readability out to a single consumer at a given time. I say "readable" loosely because of the shared distinction between "Iterable" and "Iterator", "Observable" and "Observer", "Readable" and "Reader". The Verbable has a verb, e.g., Stream and Reader have a funny relationship. The Stream seeks to ensure unicast consumption by vending to a single Reader, but ultimately a single Reader could be shared by multiple consumers and, in the case of distributing work to multiple consumers, is actually a useful feature. My interpretation is that Stream exists for possibly two reasons. On one hand, it is a convenient object for providing different consumer methods if readers turn out to be insufficient. On the other, it provides a point where the underlying fetch API can vend readability to user space and revoke the capability if the user gives it back to the system, so it can bypass userland piping. Strikes me that this is superfluous since a Reader might have directly revokable use of its read() method, or its forEach, map, reduce, all, done, or destroy methods if any of those come to be. Many of these methods could take a lock out on the underlying reader, but I suspect that is unnecessary. If the system decides to consume the stream, it can just starve userland. Conclusion: getReader does not need a name. Have Reader assimilate Stream. Of course, I probably missed something important. |
That was great.
I'm likely just dense, but I thought the whole thing was leading up to |
I’m proposing that it is sufficient to have a Reader and that all places where Stream was should just be Reader. The responsibilities previously given to a Stream can be implemented by a Reader without worrying the user. Specifically, the responsibility of guaranteeing that only the system or the user can read from the stream at any given time, can be subsumed by a Reader. From the user perspective, the ability to have multiple asynchronous readers can be a feature, and the browser can choose to starve user readers if the user gives the stream back to the browser. However, if there were a getReader() method, I would probably have called it |
I like the current Stream/Reader separation. Sharing a reader might be useful, but it is possible with the current model, and the current model enables us to define streams' behavior precisely. I don't like the idea of leaving behaviors unspecified.
Such symbol can be useful when we have an async loop syntax, but we can add it later. ES6 set has Symbol.iterator slot but it also has |
So, I'm really not seeing anything here that's materially better than getReader. (There's a lot of off-topic stuff about re-designing the streams API entirely, but this is not the thread for that.) And the arguments against getReader have not been that strong, and have counter-arguments in most cases. As such, I think it's best to just stick with Thanks for your thoughts though @youennf; I hope you felt they were given fair consideration. |
getReader name is a little bit counter-intuitive to me.
This method is really a constructor.
Its name seems to imply that it could return the same object if called several times on the same stream.
Why not simply calling it ReadableStream.createReader?
The text was updated successfully, but these errors were encountered: