Skip to content

Commit 150e1e8

Browse files
committed
Merge pull request #3434 from artem-zinnatullin/single-finally
Add Single.finallyDo()
2 parents 0b8e4e0 + 8eb7671 commit 150e1e8

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

src/main/java/rx/Single.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import rx.internal.operators.OperatorDelay;
3737
import rx.internal.operators.OperatorDoOnEach;
3838
import rx.internal.operators.OperatorDoOnUnsubscribe;
39+
import rx.internal.operators.OperatorFinally;
3940
import rx.internal.operators.OperatorMap;
4041
import rx.internal.operators.OperatorObserveOn;
4142
import rx.internal.operators.OperatorOnErrorReturn;
@@ -2020,4 +2021,25 @@ public void call(SingleSubscriber<? super T> singleSubscriber) {
20202021
public final Single<T> doOnUnsubscribe(final Action0 action) {
20212022
return lift(new OperatorDoOnUnsubscribe<T>(action));
20222023
}
2024+
2025+
/**
2026+
* Registers an {@link Action0} to be called when this {@link Single} invokes either
2027+
* {@link SingleSubscriber#onSuccess(Object)} onSuccess} or {@link SingleSubscriber#onError onError}.
2028+
* <p>
2029+
* <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/finallyDo.png" alt="">
2030+
* <dl>
2031+
* <dt><b>Scheduler:</b></dt>
2032+
* <dd>{@code doAfterTerminate} does not operate by default on a particular {@link Scheduler}.</dd>
2033+
* </dl>
2034+
*
2035+
* @param action
2036+
* an {@link Action0} to be invoked when the source {@link Single} finishes.
2037+
* @return a {@link Single} that emits the same item or error as the source {@link Single}, then invokes the
2038+
* {@link Action0}
2039+
* @see <a href="http://reactivex.io/documentation/operators/do.html">ReactiveX operators documentation: Do</a>
2040+
*/
2041+
@Experimental
2042+
public final Single<T> doAfterTerminate(Action0 action) {
2043+
return lift(new OperatorFinally<T>(action));
2044+
}
20232045
}

src/test/java/rx/SingleTest.java

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
import rx.schedulers.Schedulers;
5252
import rx.subscriptions.Subscriptions;
5353

54-
5554
public class SingleTest {
5655

5756
@Test
@@ -891,4 +890,55 @@ public void call(SingleSubscriber<? super Object> singleSubscriber) {
891890
testSubscriber.assertNoValues();
892891
testSubscriber.assertNoTerminalEvent();
893892
}
893+
894+
@Test
895+
public void doAfterTerminateActionShouldBeInvokedAfterOnSuccess() {
896+
Action0 action = mock(Action0.class);
897+
898+
TestSubscriber<String> testSubscriber = new TestSubscriber<String>();
899+
900+
Single
901+
.just("value")
902+
.doAfterTerminate(action)
903+
.subscribe(testSubscriber);
904+
905+
testSubscriber.assertValue("value");
906+
testSubscriber.assertNoErrors();
907+
908+
verify(action).call();
909+
}
910+
911+
@Test
912+
public void doAfterTerminateActionShouldBeInvokedAfterOnError() {
913+
Action0 action = mock(Action0.class);
914+
915+
TestSubscriber<Object> testSubscriber = new TestSubscriber<Object>();
916+
917+
Throwable error = new IllegalStateException();
918+
919+
Single
920+
.error(error)
921+
.doAfterTerminate(action)
922+
.subscribe(testSubscriber);
923+
924+
testSubscriber.assertNoValues();
925+
testSubscriber.assertError(error);
926+
927+
verify(action).call();
928+
}
929+
930+
@Test
931+
public void doAfterTerminateActionShouldNotBeInvokedUntilSubscriberSubscribes() {
932+
Action0 action = mock(Action0.class);
933+
934+
Single
935+
.just("value")
936+
.doAfterTerminate(action);
937+
938+
Single
939+
.error(new IllegalStateException())
940+
.doAfterTerminate(action);
941+
942+
verifyZeroInteractions(action);
943+
}
894944
}

0 commit comments

Comments
 (0)