【问题标题】:How to stop subscription by using multiple conditions with takeUntil如何通过使用 takeUntil 的多个条件来停止订阅
【发布时间】:2020-07-16 22:46:02
【问题描述】:

我想根据两个条件停止可观察订阅:

  • 时间(使用import { timer } from 'rxjs/internal/observable/timer';

  • 执行状态(使用请求中返回的对象,您将在下面看到)

发生了什么:

它只是根据时间停止执行(使用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()

如果上面的sn-p正确执行,应该停止interval$,但它没有。那是我的问题

我已经尝试过的:

  1. 我不知道两个管道是否比只使用一个这样的管道有什么不同:.pipe(takeUntil(stopConditions$), finalize(() =&gt; this.isSimulationLoading = false))。但是,我已经尝试过了,但没有成功

  2. 已尝试将 isEventFinished$ 替换为:const isEventFinished$ = of(1) 和他的订阅:timeLimiter$.pipe(first()).subscribe()。 但这也不起作用。实际上,这会阻止请求被执行(我不知道为什么)

【问题讨论】:

  • 您可能会遇到从rxjs/internal/operators/ 而不是简单的rxjs/operators 导入的问题。我知道我的 IDE 已经咬了我几次从 /internal 自动导入。
  • 还是不行。我的merge 运算符或isEventFinished$ 有问题

标签: javascript angular rxjs rxjs6


【解决方案1】:

我刚刚用 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 将其定义为 Observable(BehaviorSubject 具有默认值,Subject 没有)。

  isEventFinished$ = new Subject<boolean>();

然后,每当完成事件发生时,使用next 方法将一个值发送到isEventFinished 流中。

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);
  }
});

查看更新的闪电战。

这行得通吗?

【讨论】:

  • 代码“工作”,因为时间限制达到其限制并运行takeUntil。但是,我希望有可能在时间限制之前停止......我希望takeUntil 也能够从这里运行:isEventFinished $ .subscribe ()。尝试将 if (object.status === "FINALIZED") 更改为 if (true) 以始终执行 `isEventFinished $ .subscribe ()`。它应该停止间隔$,但它没有。那是我的问题
  • 我编辑了这个问题来解释更多。但是,总而言之,我希望isEventFinished $ 也能正常运行
  • 正如您所定义的,isEventFinished$ 似乎不是您可以发送到的 Observable。我会更新我的 stackblitz ......给我一点时间。
  • 我在这里看到了:Empty observable。我不发出特定的东西。我只想触发一个事件来停止执行
  • 非常感谢!!!我刚刚使用了这样的主题并且也工作过:new Subject&lt;void&gt;();。我不需要传递任何数据。
【解决方案2】:

您也可以像这样在 takeuntil 中使用 && 运算符:

takeUntil(this.firstCondition$ && this.secondCondition$)

【讨论】:

    猜你喜欢
    • 2021-09-03
    • 1970-01-01
    • 2017-04-10
    • 2023-03-07
    • 1970-01-01
    • 2019-05-11
    • 1970-01-01
    • 2015-09-24
    • 1970-01-01
    相关资源
    最近更新 更多