簡體   English   中英

無法弄清楚 takeUntil 行為

[英]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),
);

代碼在codeandbox.io

我測試了你的代碼和盒子。 我沒有解決方案,但我觀察到一些可能非常重要的事情。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM