Java RX, почему эта строка вызывается дважды, а эти 2 строки никогда не вызывались

#java #rx-java #reactive-programming

#java #rx-java #реактивное программирование

Вопрос:

Я новичок в Java Rx, я не знаю, является ли это правильным вопросом или нет.

У меня есть функция

     public Single<PayResponse> pay(PayRequest apiRequest) {

                return client.initiatePayment(apiRequest)
                        .doOnSuccess(initiatePaymentResponse -> {
                            System.out.println("first");
                            client.confirmPayment(initiatePaymentResponse.getPaymentId())
                                    .doOnSuccess(confirmPaymentResponse -> {System.out.println("second");doConfirmationLogic(confirmPaymentResponse ))}
                                    .doOnError(ex -> {System.out.println("thirs");ex.printStackTrace();logError(ex);});
                        })

                        .doOnError(ex -> {ex.printStackTrace();logError(ex);});
            } 
  

после выполнения этого метода, который я могу найти first , был напечатан дважды second , но ни third один из них не был напечатан

Для меня это странное поведение, потому что я ожидаю найти first и second или third .

Есть идеи?

Комментарии:

1. Источники, когда они не подписаны, ничего не делают. Вы должны использовать flatMap вместо doOnSuccess . Возможно, вы получаете first дважды, потому что вы подписываетесь на результат pay() дважды.

Ответ №1:

Чтобы начать получать передаваемые значения из наблюдаемого (например, a Single<T> ), вы должны subscribe() сначала получить его.

Вероятно, вы подписываетесь только на Single возвращенный pay дважды где-то в другом месте, и именно поэтому вы видите first напечатанный два раза. В коде, который вы показываете, я вижу, что они не подписываются ни на одно из наблюдаемых там, поэтому после этого ничего не произойдет.

Если вы хотите связать наблюдаемые, наиболее распространенным выбором будет использование flatMap оператора (есть и другие варианты).

В вашем случае это будет выглядеть примерно так:

 public Single<PayResponse> pay(PayRequest apiRequest) {

    return client.initiatePayment(apiRequest)
                .flatMap(initiatePaymentResponse -> {
                        System.out.println("first");
                        return client.confirmPayment(initiatePaymentResponse.getPaymentId();
                })
                .flatMap(confirmPaymentResponse -> {
                        System.out.println("second");
                        return doConfirmationLogic(confirmPaymentResponse);
                })
               .doOnSuccess(confirmationLogicResponse -> System.out.println("third"))
               .doOnError(ex -> {
                        ex.printStackTrace();
                        logError(ex);
                });
} 
  

Затем вы подписываетесь на сингл, возвращаемый pay где-то еще, как это:

 ...
pay(apiRequest)
     .subscribe(onSuccesValue -> {
             // The whole chain was successful and this is the value returned 
             // by the last observable in the chain (doConfirmationLogic in your case)
      }, onError {
             // There was an error at some point during the chain
      }
...
  

Я предполагаю, что все методы initiatePayment , confirmPayment , doConfirmationLogic возвращаются Singles , и это doConfirmationLogic в конечном итоге возвращает a Single<PayResponse> . Если это не так, вам нужно будет внести некоторые небольшие изменения, но вы получите общее представление о том, как работают наблюдаемые цепочки.