![](/img/trans.png)
[英]Can't figure out this behavior: 2 while loops inside a while loop
[英]Can't figure out takeUntil behavior
我不知道使用takeUntil
停止流有多合適。
Interval 必須在第一次、第三次等點擊按鈕時開始發射,並在每第二次、第四次等點擊后停止發射。
UPD:這段代碼的目的是要有一種“秒表”。 在第一次點擊時,它應該從 0 開始並計數 1、2 等。在其他點擊時,它應該開始/停止計數。
const justIndex = (_, i) => i;
const isOdd = (x) => x % 2;
const isEven = (x) => !isOdd(x);
const buttonClick$ = fromEvent(buttonEl, "click").pipe(map(justIndex));
const resumeClick$ = buttonClick$.pipe(filter(isEven));
const pauseClick$ = buttonClick$.pipe(filter(isOdd));
const intervalFrom = () =>
interval(500).pipe(
takeUntil(pauseClick$), // wtf this is not working
// takeUntil(resumeClick$), // but this is
);
const resumeInterval$ = resumeClick$.pipe(
switchMap(intervalFrom),
);
我測試了你的代碼和盒子。 我沒有解決方案,但我觀察到一些可能非常重要的事情。 fromEvent
observable 不僅在單擊按鈕時發出一個事件,而且每次發出多個事件。 首先,這可能會弄亂您的整個設置。
試試這個來驗證這一點:
const buttonClick$ = fromEvent(buttonEl, "click").pipe(
tap(n => console.log(n))
);
問題是您不共享對fromEvent(buttonEl, "click")
的訂閱fromEvent(buttonEl, "click")
這意味着每次訂閱buttonClick$
、 resumeClick$
和pauseClick$
您都在創建一個新的“單擊”偵聽器。 反過來,這意味着,當intervalFrom
被稱為takeUntil(pauseClick$)
使一個新的訂閱pauseClick$
創建使用一個新的事件偵聽器fromEvent
總是從開始0
。
因此,您想要做的是共享一個使用fromEvent
創建的事件偵聽器,以便在 RxJS 鏈中的任何地方共享點擊索引計數器:
const buttonClick$ = fromEvent(buttonEl, "click").pipe(map(justIndex), share());
您更新的演示: https : //codesandbox.io/s/rxjs-stopwatch-problem-forked-4w83h?file=/ src/ index.js
您沒有提供太多關於您想要實現的確切信息,因此我做了一些假設,希望這些假設是您想要的,或者至少足夠接近,以便您可以找出缺少的內容。
const TIME_INTERVAL = 500;
const COUNTER_INITIALLY_ON = false;
const DOM = {
counter: document.getElementById('counter') as HTMLDivElement,
toggleButton: document.getElementById('toggleButton')
} as const;
const toggleButtonClick$ = fromEvent(DOM.toggleButton, 'click');
const isCounterOn$ = toggleButtonClick$.pipe(
scan(isCounterOn => !isCounterOn, COUNTER_INITIALLY_ON),
startWith(COUNTER_INITIALLY_ON)
);
const counter$ = isCounterOn$.pipe(
switchMap(isCounterOn => {
if (!isCounterOn) {
return EMPTY;
}
return timer(0, TIME_INTERVAL).pipe(map(x => x * TIME_INTERVAL));
})
);
const updateDomSideEffect$ = counter$.pipe(
tap(counter => {
// side effects are run in a `tap` and are completely isolated
// from the rest of the streams
DOM.counter.textContent = counter;
})
);
updateDomSideEffect$.subscribe();
這是實時版本的堆棧閃電戰: https ://stackblitz.com/edit/rxjs-pniaae?devtoolsheight=60&file=index.ts
PS:我認為代碼的描述性足夠了,我不需要解釋太多,但是如果有任何不清楚的地方,請告訴我,我可以提供更多詳細信息
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.