RxJava: Is it possible to build in Completable execution into doOnSuccess or similar

Viewed 574

When some asunchronous operations need to be performed within Rx operations chain:

    private static Single<String> process(final String s) {
        return Single.just(s)
                .map(String::toUpperCase)
                .doOnSuccess(str -> saveValue1(str) // asynchronous op 1)
                .doOnSuccess(str -> saveValue2(str) // asynchronous op 2);
    }

Is it possible to write alternative of Rx chain without flatMap or blockingGet, which builds in the execution of Completable methods saveValue1, saveValue2 etc. into chain.

    private static Single<String> process(final String s) {
        return Single.just(s)
                .map(String::toUpperCase)
                .doOnSuccess(str -> saveValue1(str).blockingGet() // asynchronous op 1)
                .doOnSuccess(str -> saveValue2(str).blockingGet() // asynchronous op 2);
    }

or

private static Single<String> process(final String s) {
    return Single.just(s)
            .map(String::toUpperCase)
            .flatMap(str -> saveValue1(str).toSingleDefault(str) // asynchronous op 1)
            .flatMap(str -> saveValue2(str).toSingleDefault(str) // asynchronous op 2);
}

Example to reproduce:

package com.eisgroup.genesis.policy.core.lifecycle.commands.quote;

import io.reactivex.Completable;
import io.reactivex.Single;
import org.springframework.util.Assert;

public class Test {
    // some variables to check that asynchronous save works
    static String s1;
    static String s2; 

    public static void main(String[] args) {
        String s = process("test").blockingGet();
        Assert.hasText(s, "TEST");
        Assert.hasText(s1, "TEST");
        Assert.hasText(s2, "TEST");
    }   


    // some fake examples to show asynchronous save
    private static Completable saveValue1(String s) {
        return Completable.defer(() -> {
            s1 = s;
            return Completable.complete();
        });
    }

    private static Completable saveValue2(String s) {
        return Completable.defer(() -> {
            s2 = s;
            return Completable.complete();
        });
    }
}
1 Answers

Try this:

return Single.just(s)
                .map(String::toUpperCase)
                .flatMapCompletable(string -> Completable.mergeArray(
                        saveValue1(string).subscribeOn(Schedulers.io()),
                        saveValue2(string).subscribeOn(Schedulers.io())));

saveValue1 and saveValue2 will run in parallel ok? Don't know if that's what you want, but for efficiency and speed I do encourage it.

Related