How to ignore error and continue infinite stream?

后端 未结 10 1700
执念已碎
执念已碎 2020-12-05 06:18

I would like to know how to ignore exceptions and continue infinite stream (in my case stream of locations)?

I\'m fetching current user position (using Android-React

相关标签:
10条回答
  • 2020-12-05 06:46

    If you just want to ignore the error inside the flatMap without returning an element do this:

    flatMap(item -> 
        restService.getSomething(item).onErrorResumeNext(Observable.empty())
    );
    
    0 讨论(0)
  • 2020-12-05 06:48

    mRestService.postLocations(locations) emit one item, then complete. If an error occur, then it emit the error, which complete the stream.

    As you call this method in a flatMap, the error continue to your "main" stream, and then your stream stops.

    What you can do is to transform your error into another item (as described here : https://stackoverflow.com/a/28971140/476690 ), but not on your main stream (as I presume you already tried) but on the mRestService.postLocations(locations).

    This way, this call will emit an error, that will be transformed to an item/another observable and then complete. (without calling onError).

    On a consumer view, mRestService.postLocations(locations) will emit one item, then complete, like if everything succeed.

    mSubscription = reactiveLocationProvider.getUpdatedLocation(mLocationRequest)
            .buffer(50)
            .flatMap(locations -> mRestService.postLocations(locations).onErrorReturn((e) -> Collections.emptyList()) // can't throw exception
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe();
    
    0 讨论(0)
  • 2020-12-05 06:52

    Add my solution for this problem:

    privider
        .compose(ignoreErrorsTransformer)
        .subscribe()
    
    private final Observable.Transformer<ResultType, ResultType> ignoreErrorsTransformer =
            new Observable.Transformer<ResultType, ResultType>() {
                @Override
                public Observable<ResultType> call(Observable<ResultType> resultTypeObservable) {
                    return resultTypeObservable
                            .materialize()
                            .filter(new Func1<Notification<ResultType>, Boolean>() {
                                @Override
                                public Boolean call(Notification<ResultType> resultTypeNotification) {
                                    return !resultTypeNotification.isOnError();
                                }
                            })
                            .dematerialize();
    
                }
            };
    
    0 讨论(0)
  • 2020-12-05 07:00

    A slight modification of the solution (@MikeN) to enable finite streams to complete:

    import rx.Observable.Operator;
    import rx.functions.Action1;
    
    public final class OperatorSuppressError<T> implements Operator<T, T> {
        final Action1<Throwable> onError;
    
        public OperatorSuppressError(Action1<Throwable> onError) {
            this.onError = onError;
        }
    
        @Override
        public Subscriber<? super T> call(final Subscriber<? super T> t1) {
            return new Subscriber<T>(t1) {
    
                @Override
                public void onNext(T t) {
                    t1.onNext(t);
                }
    
                @Override
                public void onError(Throwable e) {
                    onError.call(e);
                    //this will allow finite streams to complete
                    t1.onCompleted();
                }
    
                @Override
                public void onCompleted() {
                    t1.onCompleted();
                }
    
            };
        }
    }
    
    0 讨论(0)
  • 2020-12-05 07:01

    Just pasting the link info from @MikeN's answer incase it gets lost:

    import rx.Observable.Operator;
    import rx.functions.Action1;
    
    public final class OperatorSuppressError<T> implements Operator<T, T> {
        final Action1<Throwable> onError;
    
        public OperatorSuppressError(Action1<Throwable> onError) {
            this.onError = onError;
        }
    
        @Override
        public Subscriber<? super T> call(final Subscriber<? super T> t1) {
            return new Subscriber<T>(t1) {
    
                @Override
                public void onNext(T t) {
                    t1.onNext(t);
                }
    
                @Override
                public void onError(Throwable e) {
                    onError.call(e);
                }
    
                @Override
                public void onCompleted() {
                    t1.onCompleted();
                }
    
            };
        }
    }
    

    and use it close to the observable source because other operators may eagerly unsubscribe before that.

    Observerable.create(connectToUnboundedStream()).lift(new OperatorSuppressError(log()).doOnNext(someStuff()).subscribe();
    

    Note, however, that this suppresses the error delivery from the source. If any onNext in the chain after it throws an exception, it is still likely the source will be unsubscribed.

    0 讨论(0)
  • 2020-12-05 07:03

    Try calling the rest service in a Observable.defer call. That way for every call you'll get a chance to use its own 'onErrorResumeNext' and the errors won't cause your main stream to complete.

    reactiveLocationProvider.getUpdatedLocation(mLocationRequest)
      .buffer(50)
      .flatMap(locations ->
        Observable.defer(() -> mRestService.postLocations(locations))
          .onErrorResumeNext(<SOME_DEFAULT_TO_REACT_TO>)
      )
    ........
    

    That solution is originally from this thread -> RxJava Observable and Subscriber for skipping exception?, but I think it will work in your case too.

    0 讨论(0)
提交回复
热议问题