4 回答

TA貢獻1831條經驗 獲得超10個贊
這有點過于簡單化了,但從概念上講,Reactor 源要么是懶惰的,要么是急切的。更高級的請求,如 HTTP 請求,預計會被延遲評估。另一方面,最簡單的人喜歡Mono.just或Flux.fromIterable渴望。
我的意思是調用Mono.just(System.currentTimeMillis())將立即調用該currentTimeMillis()方法并捕獲結果。所述結果僅由訂閱后發出。Mono多次訂閱也不會改變值:
Mono<Long> clock = Mono.just(System.currentTimeMillis());
//time == t0
Thread.sleep(10_000);
//time == t10
clock.block(); //we use block for demonstration purposes, returns t0
Thread.sleep(7_000);
//time == t17
clock.block(); //we re-subscribe to clock, still returns t0
運營商在那里讓這個源變得懶惰,每次有新訂閱者時defer重新評估 lambda 的內容:
Mono<Long> clock = Mono.defer(() -> Mono.just(System.currentTimeMillis()));
//time == t0
Thread.sleep(10_000);
//time == t10
clock.block(); //invoked currentTimeMillis() here and returns t10
Thread.sleep(7_000);
//time == t17
clock.block(); //invoke currentTimeMillis() once again here and returns t17

TA貢獻1853條經驗 獲得超18個贊
如果您在第一個視圖中看到簡單的話 ,它就像 Mono.just() 但不是。當您運行 Mono.just() 時,它會立即創建一個 Observable(Mono) 并重用它,但是當您使用 defer 時,它不會立即創建它,它會在每個訂閱中創建一個新的 Observable。
一個用例看差異
int a = 5;
@Override
public void run(String... args) throws Exception {
Mono<Integer> monoJust = Mono.just(a);
Mono<Integer> monoDefer = Mono.defer(() -> Mono.just(a));
monoJust.subscribe(integer1 -> System.out.println(integer1));
monoDefer.subscribe(integer1 -> System.out.println(integer1));
a = 7;
monoJust.subscribe(integer1 -> System.out.println(integer1));
monoDefer.subscribe(integer1 -> System.out.println(integer1));
}
打?。?/p>
5
5
5
7
如果您看到 mono.just 立即創建了 observable 并且即使值已更改它也不會更改,但是 defer 在 subscribe 中創建 observable 所以您將使用當前的 onSubscribe 值

TA貢獻1795條經驗 獲得超7個贊
我正在嘗試defer不同的用例。編寫以下代碼來檢查和共享,因為它可能對其他人有所幫助。我的用例是鏈接兩個Monos 并確保第一個在第二個被占用之前完成。第二個包含一個阻塞調用,其結果用于響應Monowithempty或errorresponse。沒有defer,無論第一個結果如何,都會執行我的阻塞調用。但是在使用defer阻塞調用時,只有在第一個Mono完成時才會執行。下面的代碼:
public static void main(String[] args) {
long cur = System.currentTimeMillis();
boolean succeed = true;
Mono<Integer> monoJust = Mono.create(consumer -> {
System.out.println("MonoJust inside " + (System.currentTimeMillis() - cur));
if (succeed) {
consumer.success(1);
} else {
consumer.error(new RuntimeException("aaa"));
}
});
Mono<String> monoJustStr = Mono.create(consumer -> {
System.out.println("MonoJustStr inside: " + (System.currentTimeMillis() - cur));
consumer.success("one");
});
System.out.println("##1##: Begin");
monoJust.then(evaluator() ? Mono.empty() : monoJustStr).subscribe(d -> System.out.println("##1##: "+d), e-> System.err.println(e));
System.out.println("##1##: Done: "+(System.currentTimeMillis() - cur));
System.out.println("\n\n\n##2##: Begin");
monoJust.then(Mono.defer(() -> evaluator() ? Mono.empty() : monoJustStr)).subscribe(d -> System.out.println("##2##: "+d), e-> System.err.println(e));
System.out.println("##2##: Done: " + (System.currentTimeMillis() - cur));
}
private static boolean evaluator() {
System.out.println("Inside Evaluator");
return false;
}
輸出succeed=true- 觀察“Inside Evaluator”和“MonoJust inside”的順序
##1##: Begin
Inside Evaluator
MonoJust inside 540
MonoJustStr inside: 542
##1##: one
##1##: Done: 542
##2##: Begin
MonoJust inside 544
Inside Evaluator
MonoJustStr inside: 544
##2##: one
##2##: Done: 544
下面是輸出succeed = false- 注意沒有調用評估器。
##1##: Begin
Inside Evaluator
MonoJust inside 565
java.lang.RuntimeException: aaa
##1##: Done: 567
##2##: Begin
MonoJust inside 569
java.lang.RuntimeException: aaa
##2##: Done: 569

TA貢獻1776條經驗 獲得超12個贊
初學者的簡單答案:
當在 monoJust 變量上調用 subscribe 時,它將打印一個隨機整數三次。但是在對 monoDefer 變量調用 subscribe 時,它每次都可以打印一個隨機數。
Mono<Integer> justMono = Mono.just((new Random()).nextInt(10));
//this will print same random number thrice
for(int i=0;i<3;i++)
justMono.subscribe(x -> {System.out.println("Just Mono: " + x);});
Mono<Integer> deferMono = Mono.defer(() -> Mono.just((new Random()).nextInt(10)));
//this might print three different random numbers
for(int i=0;i<3;i++)
deferMono.subscribe(x -> {System.out.println("Defer Mono: " + x);});
在 Mono.just() 中,實例化僅在第一次訂閱發生時發生一次。在 Mono.defer() 中,每次調用訂閱時都會發生實例化。
如需更多參考,請查看: https ://www.youtube.com/watch?v=eupNfdKMFL4&t= 381s at 3:15 mins
添加回答
舉報