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
Moved on
operator to Signal
#2572
Conversation
Flaky test is flaky. The only failing test is the one in |
I don't understand why we need this for |
For the most part that's true. However, sometimes you do want to synchronize side effects across multiple subscriptions, and you can't do that with multiple subscriptions! Example: originalSignal
.observeNext(sideEffects1)
originalSignal
.skipRepeats()
.flatMap(.Latest, transform: f)
.observeNext(sideEffects2) If you need to guarantee that originalSignal
.on(next: sideEffects1)
.skipRepeats()
.flatMap(.Latest, transform: f)
.observeNext(sideEffects2) So that's why I did this. |
That's true, but is this really a pattern we should encourage by adding it to the public API? My gut says no given the nuances with trying to explain the differences between |
That's an important difference, for sure, but given that the semantics are the same as in I don't know about it being a pattern we should encourage, but it's certainly something necessary. Without this addition there is no way to do this in a pure way without a potential risk for race conditions. |
There's a relation, but we can't ignore the difference between
But they don't distinguish between hot and cold signals.
The most common effect being logging which I'd feel comfortable adding. Anything else and you're probably better served by trying to integrate whatever you're doing into the signal pipeline functionally. This just doesn't feel like a problem we should attempt to solve given the other problems around complexity and understanding it introduces. @ReactiveCocoa/reactivecocoa Any other opinions? |
I know, but this is something that users of Rx still need to keep in mind. Using
How would you suggest implement what I described "integrating it into the signal pipeline functionally"? If you give me an alternate implementation, then I completely agree with everything you're saying. I'd rather not add a new operator if don't have to, but the case I'm trying to make is that it does solve a real problem.
That's another example of something that users will want to do very often: signal
.someOperator()
.on(next: { print("Log 1: \($0)") })
.flatMapErrors( ... )
.on(error: { print("Error: \($0)") })
.otherOperator
.on(next: { print("Log 2: \($0)") }) You can accomplish this by separating the signal into intermediate values (because in this case, potential race conditions don't really matter that much I suppose), but that's VERY annoying in practice and this operator would make it a lot easier to do. |
I'm not sure what you're scenario is but it seems like behavior that should be captured in a custom operator and not a generic escape hatch.
How often are you actually doing this? Outside of logging (which I've made custom operators for) I've not had a need for this. I'd much prefer to solve the logging issue directly and not add another operator that's nearly the same as |
I agree with @neilpa's objections, but at the same time, it seems weird to offer an operator for |
Especially since it solves a real problem. @neilpa you haven't answered my questions: if you can come up with a way to solve the issue above, then maybe there is no need for this, but otherwise this is actually useful. You can see the "real-world" example that made me add this: NachoSoto/AsyncImageView@3981351 With the double subscription, since the producer returned by |
I see, you're deriving from I still think this is a niche operator and would prefer to just solve the logging problem. But it looks like I'm in the minority here. |
I'm sorry Toby |
Note that
Signal.on
is equivalent toSignalProducer.on
except for thestarted
event, which wouldn't make sense onSignal
.I also added a test to verify that
disposed
is invoked at the right time.