в чем разница между map и doOnNext в flux? (т.е. проектный реактор)
В Flux функция карты также выполняется для каждого элемента в потоке. Для doOnNext функция также выполняется для каждого элемента (испускаемого) в потоке. в чем разница с точки зрения пользователя? почему существует два подобных метода? Мог бы объяснить с простотой использования.
1 ответ
TL; DR;Flux#doOnNext
для побочных эффектов,Flux#map
предназначен для синхронного отображения чего-либо из одного типа в другой.
Если мы посмотрим на документацию, то дляdoOnNext
Flux<T> doOnNext(Consumer<? super T> onNext)
Add behavior (side-effect) triggered when the Flux emits an item.
это означает в doOnNext
, мы можем выполнять побочные эффекты, такие как журнал, или делать где-нибудь вызов отдыха и т. д. и т.д. Мы также возвращаем поток типа T, который является тем же doOnNext
принимает, поэтому никаких изменений типа.
Если мы с другой стороны посмотрим на Map
:
Flux<V> map(Function<? super T,? extends V> mapper)
Transform the items emitted by this Flux by applying a synchronous function to
each item.
Мы можем прочитать, что здесь мы можем применить синхронную функцию, в основном мы можем что-то сделать с нашим выданным значением. Добавьте что-то, вычтите что-то, измените это как-нибудь, здесь мы можем это преобразовать, напримерmap
это к чему-то другому.
Если мы посмотрим на типы в map
, мы видим, что map
испустит что-нибудь super T
но он вернет то, что extends V
Это типичный шаблон java-дженериков, и если вы хотите узнать больше об этом, я рекомендую вам посмотреть, как Джошуа Блохс говорит о дженериках. Все видео - хорошие часы, которые объяснят это гораздо лучше, чем я.
Но я хочу отметить, что, используя карту, вы возвращаете другой тип. Вы получаете то, чтоsuper T
из потока, вы затем сопоставляете его с чем-то еще, что extends V
.
Просто чтобы добавить к хорошему ответу выше - я думаю, что одна важная часть, которую мне не хватало, когда я начал использовать
doOnNext()
в том, что это не "потребительский" аналог "функционального"
map
и
flatMap
.
doOnNext
это своего рода обратный вызов, который выполняется, когда издатель излучает элемент, но он не влияет на поток, а именно немедленно возвращает исходный издатель.
Пример: изначально я думал, что могу делать такие вещи, как
Mono.from()
.doOnNext(doSomethingConsumer)
.doOnNext(thenDoSomethingElseConsumer);
когда меня не интересует возвращаемое значение и что эти вещи будут применяться по порядку.
Это совершенно неверно! Фактически, оба
doOnNext()
Операторы применяются немедленно.