Not sure about exact api yet. Probably similar to observe? Or a utility that takes an expression that is tracked, and it's output can be subcribed to?
Possible streams to export:
observe(x) as streamobserve(x, prop) as stream (also for computeds)reaction() but then creating a streamReading streams:
@benjamingr what is your use case?
I want to use mobx observables inside Rx operators like:
someRx.switchMap(() => this.someMobX)...
And have someMobx be assimilated as an observable cleanly. Currently I have code like:
var autocomplete = toRx(mobxForInput).
filter(Boolean).
switchMap(value => fetch("/api/"+value)).
toMobX()
For autocomplete for example.
In addition it would be great if the other way around worked too:
@observable foo = someRxStream; // when someRxStream emits a value, mobx change to it
Ping @blesh @spion
The implementation is basically to add a [Symbol.observable] property to any object, which is a function that returns an Object with the interface:
interface IObserver {
next(value): void;
error(error): void;
complete(value): void;
}
interface ISubscription {
unsubscribe(): void;
}
interface IObservable {
subscribe(observer: IObserver): ISubscription
[Symbol.observable](): IObservable;
}
So a minimal version of this would be as simple as:
SomeObject.prototype[Symbol.observable] = function () {
return {
[Symbol.observable]() { return this; }
subscribe(observer) {
observer.next('hello world');
observer.complete();
return {
unsubscribe() { console.log('teardown here'); }
};
}
};
I hope that helps.
Also, worth noting... this is the widely used _current_ API. As the proposal in the TC39 changes (slowly), this is liable to change. However all changes that I know of should be something that supports backwards compatibility.
@blesh how is Symbol.observable typically emulated in ES5 environments? Is there a convenient for it, like with iterable: "@@observable"?
@blesh Never mind, found it
@benjamingr Figured these conversions methods are a better fit for mobxUtils (like the promise conversion methods). Just released 1.1.3 which introduces toStream / fromStream. Let me know whether it works out!
@mweststrate since Symbol.observable is a JS standard I think it would be better in core.
Optimally, I'd like:
@observable debouncedClickDelta = fromEvent(...).filter(...).map(...)
So that observable unwraps things with Symbol.observable automatically.
Additionally, if we support Symbol.observable we can do something like:
Rx.Observable
.fromEvent(button, "click")
.map(e => computed(user.firstname + user.lastName))
.distinctUntilChanged()
.scan(nameChanges => nameChanges + 1, 0)
.subscribe(nameChanges => console.log("Changed name ", nameChanges, "times"))
Which is arguably a lot cleaner.
@benjamingr I can live with the second example (note that it would be e => computed(() => user.firstname + user.lastName), makes sense.
But for the first example, how should one ever dispose the stream?
@mweststrate the same way you dispose any other observable? One MobX observable subscribing to one Rx observable.
Would a clarification help?
@benjamingr for the disposing in the first example; yes; the subscription to the observable stream should be disposed at some time. But @observable don't have an 'end of life' like mechanism (like reactions or computed values), so there is no clear point where we could hook up the unsubscription.
There is the notion of onBecome(Un)observed though, we could hook that up, but that means the value of the observable is not reliable if there are no (mobx) observer
I don't mind if instead of:
@observable debouncedClickDelta
It's:
@computed debouncedClickDelta
Or something like that.
ping
@benlesh what is Rx currently doing? Is Symbol.observable still future proof?
@benjamingr we're still using Symbol.observable. It's used by a lot of libraries now, it would take a lot of work and coordination to swing it to something else.
I suppose this is kinda outdated and nobody seems interested in implementing it. Let's close it and I will reference #2327 just in case it wants to happen there.
Most helpful comment
@benjamingr we're still using Symbol.observable. It's used by a lot of libraries now, it would take a lot of work and coordination to swing it to something else.