-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Proposal: Lifted Observable #60
Comments
I think that operator looks like as |
@xgrommx really the one you're interested in here would be |
Per a discussion yesterday with @jhusain, @trxcllnt, @benjchristensen and others: Advantage: Custom Types That ComposeThis class PaulsCustomObservable extends Observable {
lift(observerFactory) {
const o = new PaulsCustomObservable();
o.source = this;
o.observerFactory = observerFactory;
return o;
}
} Advantage: Operator Observer DecorationBy overriding lift in a custom type, or monkey patching from a script (for debugging purposes), it becomes possible to inject behaviors into all observers in an operator chain... for example: (rudimentary example) const _lift = Observable.prototype.lift;
Observable.prototype.lift = function(observerFactory) {
return _lift.call(this, new LogObserverFactory(observerFactory));
};
class LogObserverFactory {
constructor(actualObserverFactory) {
this.actualObserverFactory = actualObserverFactory;
}
create(destination) {
return new LogObserver(this.actualObserverFactory.create(destination))
}
}
class LogObserver {
constructor(destination) {
this.destination = destination;
}
next(x) {
log('nexting ' , x);
return this.destination.next(x);
}
throw(e) {
log('throwing ', e);
return this.destination.throw(e);
}
return(e) {
log('returning', e);
return this.destination.return(e);
}
} Clearly more can be done to identify the destination observer, and possibly even log a stack frame with an Error object or something, but this is to get a general idea. This will be useful in my effort at Netflix to create an OSS debugging tool for RxJS (and RxJava). Advantage: Fewer Classes?It seems, on the surface at least, that there will be fewer classes involve in operators. The current (what's in |
I'd like to put this on the Roadmap immediately, and implement it very soon since it's key to forward progress. I'll leave this issue open for community discussion though. |
This method seems very sound. I think this would be great! And definitely an improvement on what has been suggested before. |
@trxcllnt FYI: I have this conversion nearly completed in another branch... PR eminent. |
@Blesh beautiful. looking forward to reviewing it. |
Like! as well. |
This advantage made me see how lift is going to be a really good thing. PS: nitpicking on the code you probably copy-pasted from the MapObserver: next(x) {
log('nexting ' , x);
return this.destination.next(this.selector(x)); // this.selector(x) should be just x
}
I see map and mergeAll as a specialization of flatMap. ;) |
haha.. oops. Edited. |
Quoting @headinthebox in a discussion I had with him:
Subjects themselves are not a good idea for the implementation of lift, but I'm puzzled why lift(observerFactory) {
const o = new Observable();
o.source = this;
o.observerFactory = observerFactory;
return o;
}
map(selector) {
return this.lift(new MapObserverFactory(selector));
} when it could be implemented like this lift(observerTransform: (outObserver: Observer) => (inObserver: Observer)) {
const o = new Observable(outObserver => this.subscribe(observerTransform(outObserver)));
o.source = this;
return o;
}
map(selector) {
return this.lift(outObserver => {
const inObserver = Observer.create(
function next(input) {
outObserver.next(selector(input));
}
);
return inObserver;
});
} The above doesn't depend on the |
@staltz because closures are too expensive. |
Alright, that explains a lot. And what about the return of class MapObserver {
// ...
next(x) {
return this.destination.next(this.selector(x));
}
// ...
} |
@staltz in fact, when this repository first started, we experimented with two implementations of observable: 1. The Observer/Observable pairing, and 2. Lift (as you've proposed it above) ... 1 was orders of magnitude faster. Mostly because it avoided closure. We've arrived at where we are (in master) with perf tests. Once this lift branch is fully functional, we'll perf test, and perf wins. (I'm sure it will be the same or better than master, though) |
Done in master. |
Add tests for Observable to verify that the most important codebase-wide features brought by the lift architecture are satisfied. Refers to discussion in ReactiveX#60.
Add tests for Observable to verify that the most important codebase-wide features brought by the lift architecture are satisfied. Refers to discussion in ReactiveX#60.
Add tests for Observable to verify that the most important codebase-wide features brought by the lift architecture are satisfied. Refers to discussion in ReactiveX#60.
Add tests for Observable to verify that the most important codebase-wide features brought by the lift architecture are satisfied. Refers to discussion in ReactiveX#60.
Add tests for Observable to verify that the most important codebase-wide features brought by the lift architecture are satisfied. Refers to discussion in #60.
I may be wrong but the lift method reminds me of Dart's transform method. |
@EmmanuelOga yep, pretty much identical |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Implement Observable operators in terms of
lift
.What is
lift
?lift
is a function that takes a source Observable and an Observer factory function, and returns a new Observable:Though this is the formal definition, we should make the following changes to our Observable's
lift
:lift
on the Observable prototype.source
argument in favor of usingthis
as the source.observerFactory
fromfunction
to theObserverFactory
interface. This interface requires the implementor to have acreate
function that accepts an Observer and returns an Observer.lift
has the following advantages:lift
on their Observable subclass.For example, here's how
map
is implemented in terms oflift
:The text was updated successfully, but these errors were encountered: