如何在执行Flux.map()时处理错误

时间:2016-03-26 15:39:15

标签: java reactive-programming project-reactor

我试图弄清楚在Flux中映射元素时如何处理错误。

例如,我正在将CSV字符串解析为我的一个业务POJO:

myflux.map(stock -> converter.convertHistoricalCSVToStockQuotation(stock));

这些行中的一些可能包含错误,因此我在日志中得到的是:

 reactor.core.publisher.FluxLog:  onNext([SOME_BOGUS_QUOTE]@38.09 (Fri Apr 08 00:00:00 CEST 2016) H(38.419998)/L(37.849998)/O(37.970001))
 reactor.core.publisher.FluxLog:  onNext([SOME_BOGUS_QUOTE]@38.130001 (Thu Apr 07 00:00:00 CEST 2016) H(38.189999)/L(37.610001)/O(37.799999))
 reactor.core.publisher.FluxLog:  onError(java.lang.IllegalArgumentException: Invalid CSV stock quotation: SOME_BOGUS_QUOTE,trololo)
 reactor.core.publisher.FluxLog:  java.lang.IllegalArgumentException: Invalid CSV stock quotation: SOME_BOGUS_QUOTE,trololo

我在API中读到了一些错误处理方法,但大多数都提到返回“错误值”或使用回退Flux,如下所示:

Flux.onErrorResumeWith(myflux, x -> Mono.fromCallable(() -> ... do stuff);

然而,在我的myflux中使用它意味着再次处理整个光通量。

那么,有没有办法在处理特定元素时处理错误(即忽略它们/记录它们)并继续处理其余的通量?

使用@akarnokd解决方法更新

public Flux<StockQuotation> getQuotes(List<String> tickers)
{
    Flux<StockQuotation> processingFlux = Flux.fromIterable(tickers)
    // Get each set of quotes in a separate thread
    .flatMap(s -> Mono.fromCallable(() -> feeder.getCSVQuotes(s)))
    // Convert each list of raw quotes string in a new Flux<String>
    .flatMap(list -> Flux.fromIterable(list))
    // Convert the string to POJOs
    .flatMap(x -> {
            try {
                return Flux.just(converter.convertHistoricalCSVToStockQuotation(x));    
            }
            catch (IllegalArgumentException ex){
                System.out.println("Error decoding stock quotation: " + x);
                return Flux.empty();
            }
    });

    return processingFlux;
}

然而,这可以作为一种魅力,因为你可以看到代码不像以前那么优雅。 Flux API是否有任何方法可以执行此代码的操作?

retry(...)
retryWhen(...)
onErrorResumeWith(...)
onErrorReturn(...)

5 个答案:

答案 0 :(得分:14)

您需要flatMap,如果处理失败,您将返回空序列:

myflux.flatMap(v -> {
    try {
        return Flux.just(converter.convertHistoricalCSVToStockQuotation(stock));
    } catch (IllegalArgumentException ex) {
        return Flux.empty();
    }
});

答案 1 :(得分:11)

如果您想使用Reactor 3的方法来处理异常,可以使用Mono.fromCallable

flatMap(x -> 
    Mono.fromCallable(() -> converter.convertHistoricalCSVToStockQuotation(x))
        .flux()
        .flatMap(Flux::fromIterable)
        .onErrorResume(Flux::empty)
)

不幸的是没有Flux.fromCallable,所以假设callable返回一个列表,你必须手动将它转换为Flux。

答案 2 :(得分:4)

使用当前版本的Reactor 3,添加了很多方法。所以我们可以这样做:

Flux.onErrorResume(error -> { 
        System.out.println("Error decoding stock quotation: " + e);
        return Flux.empty();
    });

查看有关如何处理错误的更多信息here

答案 3 :(得分:1)

您可以使用onErrorContinue。 它允许通过删除故障元素并继续后续元素来从错误中恢复。

答案 4 :(得分:1)

> Sno | avg_qty
> :-- | ------:
> S1  |      50
> S3  |      83
> S4  |      40