[英]RxJS: takeUntil ignores Subject event
在下面的代碼示例中,目的是通過向 Subject mid$
發出 1 來阻止second$
的事件。
import { Subject, timer } from "rxjs";
import { switchMap, takeUntil, tap } from "rxjs/operators";
const first$ = timer(1000);
const second$ = timer(2000);
const mid$ = new Subject();
first$.pipe(
tap(() => {
mid$.next(1);
}),
switchMap(() => second$.pipe(
takeUntil(mid$),
tap(() => console.log("MISSED!"))
)),
).subscribe();
mid$.subscribe(() => console.log("RECEIVED"));
但由於控制台顯示的某些原因,它不起作用:
RECEIVED
MISSED!
即mid$.next(1);
takeUntil(mid$)
不考慮
這里的邏輯是什么?
我注意到如果我替換 line mid$.next(1);
與timer(0).subscribe(() => mid$.next(1));
它按預期工作,但我想知道在 RxJS 中處理此類情況的正確方法是什么。
takeUntil 僅在下一次observable 發射時取消訂閱。 它不知道之前是否已經發出了 observable。
const first$ = timer(1000);
const second$ = timer(2000);
const mid$ = new Subject();
first$.pipe(
tap((first) => {
console.log('first', first)
mid$.next(1);
console.log('first', first)
}),
switchMap(() => second$.pipe(
tap((second) => console.log('second', second)),
takeUntil(mid$), // Unsubscribing next time mid$ emits
tap(() => console.log("MISSED!"))
)),
).subscribe(second => console.log('final', second));
mid$.subscribe(() => console.log("RECEIVED"));
這將記錄
// 1s passes
first 0
RECEIVED
first 0
// 1s passes
second 0
MISSED!
final 0
這是正在發生的事情:
一秒鍾過去了。 first$ 發出,然后你 switchMap 到 second$。 再過一秒,第二個$ 發出。 只是現在你告訴它在 mid$下一次發出后取消訂閱。 然而 mid$ 已經發出(並且永遠不會再次發出)。 如果您將 second$ 替換為 interval(2000) 您會明白我的意思。 “錯過了。” 將每 2 秒永久記錄一次。
它不像這樣按預期工作
const first$ = timer(1000);
const second$ = timer(2000);
const mid$ = new Subject();
first$.pipe(
tap(() => {
mid$.next(1);
}),
switchMap(() => second$.pipe(
takeUntil(mid$),
tap(() => console.log("MISSED!"))
)),
).subscribe();
因為當mid$.next(1);
到達時, switchMap
的內部 observable 尚未創建。 所以, takeUntil
還沒有訂閱那個mid$
主題。
它適用於timer(0).subscribe(() => mid$.next(1));
(這與setTimeout(() => mid$.next(), 0)
大致相同),因為在這種情況下,當mid$
發出時, switchMap
已經創建了內部 observable。
解決此問題的快速方法可能涉及使用BehaviorSubject
而不是Subject
,因為BehaviorSubject
會將最后發出的值發送給新訂閱者:
const first$ = timer(1000);
const second$ = timer(2000);
const mid$ = new BehaviorSubject(null);
first$.pipe(
tap(() => {
mid$.next(1);
}),
switchMap(() => second$.pipe(
// here, when `mid$` is subscribed, the subscriber will receive `1`
// and the entire inner observable will complete
takeUntil(mid$),
tap(() => console.log("MISSED!"))
)),
).subscribe();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.