tc39 / proposal-observable

Observables for ECMAScript
https://tc39.github.io/proposal-observable/
3.06k stars 90 forks source link

Symbol.observer? #89

Open benlesh opened 8 years ago

benlesh commented 8 years ago

I think that Symbol.observable is a fine interop point. I was going through to add Observable interoperability to a project that isn't rx-related, and I noticed something: While sometimes I wanted to be able to subscribe to another object with [Symbol.observable](), other times I wanted to use the other object as an observer.

Would it be worth considering a Symbol.observer? That is, a symbol that can be used to identify an object as an observer. Could be useful for generators as well as custom objects.

interface Observerable {
  [Symbol.observer](): Observer<T>
}

(lol... "Observerable", I'm kidding there, of course).

benjamingr commented 8 years ago

Dumb question: why do we need a special symbol for this? Won't any object with next/error/complete "just work" in place of an observer?

RangerMauve commented 8 years ago

I agree with @benjamingr, Promises have a concept of thennables based on whether the object has a then function on it, I think that Observers could be detected the same way.

Edit: Though Promises/A+ didn't really have Symbols to consider when they were defining the spec, so I'm not sure it's relevant.

benjamingr commented 8 years ago

@RangerMauve it would have been easy and still is to add a Symbol for promises resolving (although amusingly nominally typed languages like C#'s use a structural interface GetAwaiter :P). Work has been done on promises since (async/await) and there didn't seem to be an urgent need for this.

That said - I'm not saying we shouldn't have a Symbol here - just that I do not understand its purpose.

benlesh commented 8 years ago

Dumb question: why do we need a special symbol for this? Won't any object with next/error/complete "just work" in place of an observer?

I see your argument, couldn't anyone just create a POJO with next, error or complete on it for any API? I suppose. But if the API author wanted to provide a sanctioned way for any reactive library to use one of their types as an observer, this symbol could provide that.

Let's say console had some hypothetical Symbol.observer implementation:

console[Symbol.observer] = function symbolObserver() {
  return {
    next: (value) => this.log(value),
    error: (err) => this.error(value),
    complete: () => this.info('complete', value),
  }
};

Then you could log out all observable emissions like so:

someObservable.subscribe(console);

Probably the same reason any object with a subscribe method doesn't "just work" as an Observable.

  1. Because symbols work as an unobtrusive way to amend to an API.
  2. next, error and complete are a lot of methods to add as a requirement to an existing type, and that existing type might already have a method named next, for example.
  3. If the Observer spec changes to require another method like start or onStart, then it's again less invasive on the API that wants to implement it.
benlesh commented 8 years ago

I think that Observers could be detected the same way.

So a "nextable"? You could just be detecting an iterator, though.

zenparsing commented 8 years ago

It's a cool idea, and one that I hadn't considered. I'm comfortable leaving it aside for now, though, until we get through the changes to of/from/etc.

chicoxyzzy commented 8 years ago

any updates on this?

dead-claudia commented 8 years ago

I've just been subclassing Observable to also quack like an Observer. If only that were possible in RxJS, but I believe that possibility is being considered now there, too.

benlesh commented 8 years ago

@isiahmeadows... In RxJS you're looking for subjects. You can even "glue" an observer to an observable with Subject.create to make a subject. Which is just an observable that "quacks like an observer".

dead-claudia commented 8 years ago

@blesh I'm aware of RxJS's Subjects, it's just that I'm limited to any-observable for my application (it's a library). I also need subclassing support for other reasons (e.g. class Ref extends Observable), and RxJS doesn't provide those facilities yet, so I kind of have to roll my own.

dead-claudia commented 8 years ago

It's pretty straightforward to do, though.

benlesh commented 8 years ago

RxJS doesn't provide those facilities yet

As far as I know RxJS 4 does, and RxJS 5 definitely does support subclassing Observable.

You should file a ticket on https://github.com/reactivex/rxjs if you're having an issue subclassing, or there's a particular features you're requesting.

dead-claudia commented 8 years ago

@blesh RxJS 5 doesn't fully support subclassing to any useful extent as far as I can tell.

benlesh commented 8 years ago

@isiahmeadows 🙂 I wrote a majority of RxJS 5. While there are minor ergonomics gaps in subclassing Observables (which is what we're discussing in that issue), they are very minor. We subclass Observable throughout the library, and it's something that we've done in redux-observable and others have done Angular 2 related libraries.

Either way, this is all off-topic. 🙂 But you should feel free to subclass RxJS 5 Observables.

dead-claudia commented 8 years ago

@blesh Okay. I'll take your word for it, then.