繁体   English   中英

在RxJava中,如何在Observable之外反映/提取故障?

[英]In RxJava, how to reflect/extract a failure outside of an Observable?

我们有一个StoreService,它调用一个update(key,content)方法,该方法正在使用couchbase客户端进行get-> change_content-> replace。

作为该过程的一部分,我们使用Observable retryWhen来处理异常。 如果重试次数超过了最大重试次数,它只会传递Exception,然后触发观察者的onError方法。

万一无法处理错误,我们想做的就是将update(key,content)方法中的Exception抛出给调用它的StoreService,但我们没有这样做。

到目前为止,我们已经尝试了以下方法,但均未成功:

  1. 从onError方法引发异常,但不会从Observable中抛出该异常。
  2. 抛出RuntimeException,但效果不佳。
  3. 使用其中包含boolean isFailed成员的DTO:我们在Observable之外创建DTO,如果发生错误,我们将到达订户的onError,将DTO的isFailed设置为true。 Observable完成后,我们检查DTO是否失败,如果是,则抛出异常。 那也不起作用-onError中发生的更改没有传播到Observable之外(为什么?)

这是伪代码:

 public void update(String key, ConversationDto updateConversationDto) {

    ObservableExecution observableExecution = new ObservableExecution();

    Observable
            .defer(... get the document from couchbase ...) 
            .map(... handle JSON conversion and update the document ...)
            .flatMap(documentUpdate -> {
                return couchbaseClient.getAsyncBucket().replace(documentUpdate);
            })
            .retryWhen(new RetryWithDelay(3, 200))
            .subscribe(
                    n -> logger.debug("on next update document -> " + n.content()),
                    e -> {
                        //logger.error("failed to insert a document",e);
                        observableExecution.setFailure(e);
                    },
                    () -> logger.debug("on complete update document")

            );
    // this is never true
    if (observableExecution.isFailed()) {
        final Throwable e = observableExecution.getFailure();
        throw new DalRuntimeException(e.getMessage(), e);
    }
}

这是retryWhen代码:

public Observable<?> call(Observable<? extends Throwable> attempts) {
    return attempts
            .flatMap(new Func1<Throwable, Observable<?>>() {
                @Override
                public Observable<?> call(Throwable errorNotification) {
                    if (++retryCount < maxRetries) {
                        // When this Observable calls onNext, the original
                        // Observable will be retried (i.e. re-subscribed).
                        logger.debug(errorNotification + " retry no. " + retryCount);
                        return Observable.timer(retryDelayMillis,
                                TimeUnit.MILLISECONDS);
                    }

                    // Max retries hit. Just pass the error along.
                    logger.debug(errorNotification + " exceeded max retries " + maxRetries);
                    return Observable.error(errorNotification);
                }
            });
}

非常感谢您的帮助!

订阅将异步运行,因此isFailed()检查将始终在e -> setFailure(e)代码运行之前立即运行。

正确的方法是从update()方法返回Observable并在StoreService中对其进行StoreService 这样一来,您就可以在处理成功和失败时收到通知。

我同意@Ross:从概念上讲Observable应该由update()返回。 我可以提出的唯一简化方法是使用局部可变变量而不是ObservableExecution DTO:

public void update(String key, ConversationDto updateConversationDto) {
    final Throwable[] errorHolder = new Throwable[1];

    Observable
        .defer(... get the document from couchbase ...) 
        .map(... handle JSON conversion and update the document ...)
        .flatMap(documentUpdate -> {
            return couchbaseClient.getAsyncBucket().replace(documentUpdate);
        })
        .retryWhen(new RetryWithDelay(3, 200))
        .subscribe(
                n -> logger.debug("on next update document -> " + n.content()),
                e -> {
                    //logger.error("failed to insert a document",e);
                    errorHolder[0] = e;
                },
                () -> logger.debug("on complete update document")

        );

    if (errorHolder[0] != null) {
        final Throwable e = errorHolder[0];
        throw new DalRuntimeException(e.getMessage(), e);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM