代码之家  ›  专栏  ›  技术社区  ›  62mkv

从过滤后的序列中获取最后一个未过滤结果的惯用方法是什么?

  •  1
  • 62mkv  · 技术社区  · 7 年前

    我必须在一行中多次调用外部API方法,直到尝试不足或收到肯定的响应为止。如果尝试次数不足,我仍然希望使用(出于日志记录/诊断目的)最新的未成功响应。目前我是这样做的:

            class SimpleWrapper<T> {
            private T data;
    
            public T getData() {
                return data;
            }
    
            public void setData(T data) {
                this.data = data;
            }
        }
    
        SimpleWrapper<String> state = new SimpleWrapper<>();
    
        Observable<Response> getLogObservable = Observable.interval(checkInterval, TimeUnit.SECONDS)
                .take(checkCount)
                .flatMap(ignored -> api.check())
                .doOnNext(response -> {
                    logger.info("Check response: {}", response.getMessage());
                    state.setData(response.getMessage());
                })
                .firstOrDefault(null, HubLogsApiResponse::isSuccess)
                .flatMap(response -> {
                    if (response == null) {
                        return Observable.error(new RuntimeException(String.format("Last call to check was unsuccessful: %s", state.getData())));
                    } else {
                        return Observable.just(response);
                    }
                })
    

    这很难看,需要我使用副作用,但我不知道如何才能做到这一点。

    有什么建议吗?

    1 回复  |  直到 7 年前
        1
  •  0
  •   Bob Dalgleish Denis K.    7 年前

    问题:发出一系列请求,要么返回第一个成功的请求,要么返回最后一个作为错误的请求。

    如果我们引入 Pair ,我们可以将 interval 使用API请求。然后,可以在不设置全局变量的情况下检查终止条件。

    Observable<Response> getLogObservable = 
      Observable.interval(checkInterval, TimeUnit.SECONDS)
            .flatMap(requestNumber -> api.check()
                                        .map(response -> 
                                             new Pair(requestNumber+1, response))
            .flatMap(pair -> mapResponse( pair ) )
            .take( 1 );
    
    Observable<Response> mapResponse( Pair<Long, Response> response ) {
      if ( response.getSecond().isSuccess() ) {
        return Observable.just( response.getSecond() );
      }
      if ( response.getFirst() >= checkCount ) {
        Observable.error(
          new RuntimeException(String.format("Last call to check was unsuccessful: %s", 
                pair.getSecond().getData())));
      }
      return Observable.empty();
    }
    

    mapResponse 仅当计数器已运行时,才会产生包含最新响应的错误。否则,它将返回一个成功的响应或一个空的可观测值。