Rxjava: Calling to Observable.toBlocking(). Always a bad practice?

Created on 20 May 2016  路  5Comments  路  Source: ReactiveX/RxJava

Hi.

I have a library which returns observables. And I have another one which require to return the data in a synchronous way.

Particularly, I鈥檓 talking about OkHttp Interceptors. I need to retrieve the oauth token in order to add it as header. But this data comes from an observable.

public class TwitterInterceptor implements Interceptor {
    @Override public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Request newRequest = request.newBuilder()
                .addHeader("oauth_token", RxToken.getTwitterToken().toBlocking().first())
                .build();
        return chain.proceed(newRequest);
    }
}

Calling toBlocking().first() is the only way I can think to solve this problem. But I do not know if calling toBlocking() may have some unexpected effects (I mean I know that this observable resolves its task reading from disk or memory, so it is not a really heavy task). But because it seems to be not recommended to use it in production code, as a general rule.

Thanks.

Question

Most helpful comment

toBlocking gets you out of the reactive world and is generally fine if you have to bridge legacy, non-reactive APIs with it. In your example, if you can't change the method to Observable<Response> intercept(Chain chain), toBlocking is acceptable tradeoff.

However, if you are in the reactive world and suddenly want to use toBlocking inside a sequence, there are almost always ways to not do that. A typical mistake that comes up is something like this:

source.map(v -> someAPI(v).toBlocking().first())...

Instead, you should be using any of the flatMap, concatMap, etc.

source.concatMap(v -> someAPI(v))...

All 5 comments

toBlocking gets you out of the reactive world and is generally fine if you have to bridge legacy, non-reactive APIs with it. In your example, if you can't change the method to Observable<Response> intercept(Chain chain), toBlocking is acceptable tradeoff.

However, if you are in the reactive world and suddenly want to use toBlocking inside a sequence, there are almost always ways to not do that. A typical mistake that comes up is something like this:

source.map(v -> someAPI(v).toBlocking().first())...

Instead, you should be using any of the flatMap, concatMap, etc.

source.concatMap(v -> someAPI(v))...

Thanks for the explanation David.

I've got a question about this. In Android, shouldInterceptRequest on a WebClient requires a returned value, either null or a WebResourceResponse. I would like to avoid having a blockingFirst() call. Ideally I would like to pass a reference to the return value into the Observable chain and then make the decision on blocking later on. But I can't see how to do this.

@tomgallagher almost always is. If you have something specific, please ask the wider audience of StackOverflow about it.

OK thanks.

Was this page helpful?
0 / 5 - 0 ratings