簡體   English   中英

如何通過使用 takeUntil 的多個條件來停止訂閱

[英]How to stop subscription by using multiple conditions with takeUntil

我想根據兩個條件停止可觀察訂閱:

  • 時間(使用import { timer } from 'rxjs/internal/observable/timer';

或者

  • 執行狀態(使用請求中返回的 object,您將在下面看到)

發生了什么:

它只是根據時間停止執行(使用import { timer } from 'rxjs/internal/observable/timer';

這是我當前的代碼:

出於示例目的,屬性、變量及其值的名稱已更改:

import { finalize } from 'rxjs/internal/operators/finalize';
import { interval } from 'rxjs/internal/observable/interval';
import { timer } from 'rxjs/internal/observable/timer';
import { takeUntil, first } from 'rxjs/operators';
import { merge, EMPTY, of } from 'rxjs';

.
. // Attributes and Class declaration here
.


async startProcess(): Promise<void> {

    this.isProcessLoading = true;

    const { someId } = await this.exampleService.execute().toPromise();

    const interval$ = interval(1000);
    const timeLimiter$ = timer(10000);

    const request$ = this.exampleService.doRequest();
    
    const isEventFinished$ = EMPTY;

    // My goal here is for the result of this function to return an observable that notifies 
    // if the first parameter emits an event OR if the second parameter emits another. That is, I want to notify if any condition is valid
    const stopConditions$ = merge(isEventFinished$, timeLimiter$);

    const handleSuccess = (object: MyType) => {

      if (object.status === 'FINALIZED') {

        this.object = object;
        isEventFinished$.subscribe();
      }
    };

    const handleError = () =>  this.showErrorComponent = true;

    interval$
    .pipe(takeUntil(stopConditions$))
    .pipe(finalize(() => this.isSimulationLoading = false))
    .subscribe(() => request$.subscribe(handleSuccess, handleError));
}

代碼“有效”是因為timeLimiter$在 10 秒后觸發takeUntil 但是,我希望有可能在時間限制之前停止......

我希望 takeUntil 也能夠從這里運行:

isEventFinished$.subscribe()

如果上面的代碼片段正確執行,它應該停止間隔 $,但它沒有。 那是我的問題

我已經嘗試過的:

  1. 我不知道兩個管道是否比只使用一個這樣的管道有什么不同: .pipe(takeUntil(stopConditions$), finalize(() => this.isSimulationLoading = false)) 但是,我已經嘗試過了,但沒有奏效

  2. 已經嘗試將此isEventFinished$替換為: const isEventFinished$ = of(1)和他的訂閱: timeLimiter$.pipe(first()).subscribe() 但這也不起作用。 實際上,這會阻止請求被執行(我不知道為什么)

我剛剛用 Stackblitz 嘗試了這段代碼,它“工作”了……但我不確定你到底想做什么? 然后我做了一些更新,以更好地了解發生了什么。

在此處查看 Stackblitz: https://stackblitz.com/edit/angular-takeuntil-deborahk

關鍵變化:

const stopConditions$ = merge(this.isEventFinished$, timeLimiter$).pipe(
  tap(s => console.log("stop", s))
);

interval$.pipe(takeUntil(stopConditions$)).subscribe({
  next: handleSuccess,
  error: handleError,
  complete: () => {
    this.isSimulationLoading = false;
    console.log("isSimulationLoading", this.isSimulationLoading)
  }
});

這有幫助嗎?

編輯:我添加了一個“完成”按鈕來模擬任何會導致完成操作的操作。

通過將 isEventFinished 聲明為 Subject 或 BehaviorSubject 將isEventFinished定義為 Observable(BehaviorSubject 有默認值,Subject 沒有)。

  isEventFinished$ = new Subject<boolean>();

然后,每當完成事件發生時,使用next方法將一個值發送到isEventFinished stream 中。

this.isEventFinished$.next(true);

那么這段代碼應該可以工作:

const stopConditions$ = merge(this.isEventFinished$, timeLimiter$).pipe(
  tap(s => console.log("stop", s))
);

interval$.pipe(takeUntil(stopConditions$)).subscribe({
  next: handleSuccess,
  error: handleError,
  complete: () => {
    this.isSimulationLoading = false;
    console.log("isSimulationLoading", this.isSimulationLoading);
  }
});

查看更新的閃電戰。

那樣有用嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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