- From: Jake Verbaten <raynos2@gmail.com>
- Date: Sat, 13 Apr 2013 14:47:18 -0700
- To: "Tab Atkins Jr." <jackalmage@gmail.com>
- Cc: Domenic Denicola <domenic@domenicdenicola.com>, "www-dom@w3.org" <www-dom@w3.org>
- Message-ID: <CAMCMjp3yCMFuOGf-WXxzoZK1BmH6G3VFgPi_TkxYEwUL2mQiiQ@mail.gmail.com>
> Because Dart Streams clearly do give you the whole history, according to the examples on the page Domenic linked. I would interpret this as `when you call listen()` it starts emitting events. If you call `listen()` multiple times it will throw an exception unless it's in "broadcast" mode. In "broadcast" mode multiple people can call `listen()` and each individual would get the events that happened after they call `listen()` > This appears to be almost exactly what I proposed, no? It uses a value() for the current value, rather than a next() for the next value, but these can coexist usefully. The usage of `next()` and `listen()` may cause race conditions unless you garantuee that the `next()` Future fulfills before any events occur in the `listen()` callback. If your going to enforce that guarantee you might as well make `next()` or `value()` synchronous. > Further, a value changing over time can still cause an error, and stop being valid. When interpreted as a property that you observe, it's not the property that is a value over time that causes the error, it's the entire object that causes the error. For simplicity you may want to have the error handling thing be out of scope for the actual properties that change. > If the value changes and you dont' push it to your listeners, you're doing it wrong. If you're doing it right, the "last value" is always meaningful, because it's the *current* value. A stream should always push the event to all listeners. The "last value" being meaningful only holds for stateful streams. You can't just turn arbitrary EventTarget's into streams because the last "focus" event emitted may not make sense as a "current value" > So, let's still design a Stream abstraction, but I can go ahead and do my own API design without worrying about it for now. It should be noted that there is work going on for non-stateful streams in ( https://dvcs.w3.org/hg/streams-api/raw-file/tip/Overview.htm ) aimed at unifying the file reading, xhr and other streaming APIs. The return type of `Object.observe` may need a better name then "Stream" On Fri, Apr 12, 2013 at 11:05 AM, Tab Atkins Jr. <jackalmage@gmail.com>wrote: > On Thu, Apr 11, 2013 at 6:56 PM, Jake Verbaten <raynos2@gmail.com> wrote: > > Tab Atkins wrote: > >> Hm, Streams *might* work. However, it looks like they usually still > >> fall prey to the "can only see the *next* update after subscribing" > >> problem. If we had something that would inform you of the > >> most-recently-published value as well when you subscribed, it would > >> probably work better. If I'm reading correctly, they also > >> automatically feed you the entire history of the stream, while the > >> use-cases I'm thinking of just need to know the "current" state and > >> future states. > > > > Streams should not feed you the entire history, they should just give you > > new events. > > Are you saying that Dart Streams specifically shouldn't, or that > "streams" in general shouldn't? Because Dart Streams clearly do give > you the whole history, according to the examples on the page Domenic > linked. You *first* fill a stream with data from an iterable, *then* > listen to the stream, and you get all the data you'd already pushed > in. > > > I also feel that progress is out of scope for Future as they represent a > > single value to be known in the future with correct error propagation > > mechanisms. > > Once again, this is a narrow view. "A single value to be known in the > future" can easily and naturally be augmented with progress toward the > completion of that value. For example, check out the Font#ready() > function I've sketched at > <http://wiki.csswg.org/ideas/font-load-futures>. Right now it's a > simple Future, which completes/rejects when the font loads/errors. > But font load status is actually tri-state, going from "not loaded" to > "loading" to "loaded", and it's reasonable to augment the Future with > the ability to observe the current state of the Font so that, for > example, a web-based authoring tool could have UI for the current > state of the font. > > > As mentioned in another thread ( > > http://lists.w3.org/Archives/Public/www-dom/2013AprJun/0022.html ) you > > probably want to look into an FRP style signal ( > > http://en.wikipedia.org/wiki/Functional_reactive_programming ) which is > a > > representation of a value over time. It's the only async data structure I > > know of that specifically models current state at a moment in time. > > Yes, what I'm asking for is more-or-less an FRP signal. > > > RXJS ( https://github.com/Reactive-Extensions/RxJS/wiki/Observable ) and > > bacon ( https://github.com/raimohanska/bacon.js#property ) have > > implementations of this idea. Elm (a compile to JavaScript language) also > > has good implementations of this idea ( > > http://elm-lang.org/learn/What-is-FRP.elm ) > > (Btw, the RxJS docs are completely impenetrable. Most of the > documentation doesn't even exist, and the stuff that does exist is > barely described. The API has kinda horrible naming in parts, too.) > > > It would probably look like > > > > interface Signal { > > void listen(valueListener); > > Any value(); > > } > > > > Where you can ask it for it's current value synchronously by calling > value() > > and you can listen to any future changes by calling listen(function). > > This appears to be almost exactly what I proposed, no? It uses a > value() for the current value, rather than a next() for the next > value, but these can coexist usefully. > > > It > > should be noted that the representation of a value over time is not a > > representation for an asynchronous task that may cause an error, that's a > > seperate thing. > > Not really. The progress of an async task is a value over time. The > two aren't *intrinsically* linked, but neither are they intrinsically > separate. > > Further, a value changing over time can still cause an error, and stop > being valid. > > > Your font future may have an attribute called "completionStatus" that is > a > > signal. It should also be noted that signals require an initial value. In > > the case of the loading status of a font it would default to 0 (assuming > > it's modeled as a number from 0 to 100). > > If value() returns a future for the value, rather than returning the > value syncly, then you don't need an initial value either - the > value() future just wouldn't be resolved initially. (After at least > one value is pushed, the future returned by value() is always already > completed.) > > Alternately, the initial value can just be null/undefined. That works > just fine for most things. > > > It should also be noted that streams do not have a notion of "current > value" > > for good reasons. The notion of "current value" means that a) you need to > > maintain state on something that could be stateless. b) it needs to have > an > > initial state before it has started and c) you need to look at the state > of > > a stream in between two events and that state needs to make coherent > sense. > > Just saying that the state is the last event is not always a meaningful > > thing. > > If the value changes and you dont' push it to your listeners, you're > doing it wrong. If you're doing it right, the "last value" is always > meaningful, because it's the *current* value. > > ~TJ >
Received on Saturday, 13 April 2013 21:47:46 UTC