如何停止 rxjs interval/timer

How to stop an rxjs interval/timer

我找到了几个示例,其中可以 start/stop 一个 rxjs 计时器或间隔,但是我无法让我的计时器停止。

HTML 以下片段:

仅供参考:第一次按 autoPlay() 将触发我的自动播放间隔。再次点击将关闭自动播放。

我的 Angular (click) 事件将触发 autoPlay() 就好了,我的 this.toggleMe 按预期工作(每 1 秒在 true 和 false 之间翻转值)。

<mat-slide-toggle #toggleMe color="primary" [checked]="toggleMe"></mat-slide-toggle>
<div>
  <mat-icon svgIcon="auto-flipper" (click)="autoPlay()"></mat-icon>
</div>

<!-- example of the two panels that are shown/hidden based on slide-toggle above -->
<show-panel-one
  [hidden]="toggleMe.checked"
></show-panel-one>

<show-panel-two
  [hidden]="!toggleMe.checked"
></show-panel-two>

但是,我正在尝试通过 Subject 清除间隔;即,this.stopPlay$.next();。但它不会停止间隔。

import { Component, ... } from "@angular/core";

@Component({
    selector: "auto-play",
    templateUrl: "./auto-play.component.html",
})

export class MyTestComponent implements OnChanges, OnInit {

autoPlay = false;
stopPlay$: Subject<any> = new Subject();
@ViewChild("examToggle") examToggle: MatSlideToggle;

constructor() {}

autoPlay(): void {
 this.autoPlay = !this.autoPlay;
 if (!this.autoPlay) {
  this.stopPlay$.next();
 }
 const autoPlayInter = interval(1000);
 autoPlayInter.subscribe(() => {
  this.toggleMe.checked = !this.toggleMe.checked;
 });
 autoPlayInter.pipe(
  // map((_) => {}),
  takeUntil(this.stopPlay$),  // Shouldn't the .next() above trigger the timer stop ?
 );        
 }
 
}

如果知道我做错了什么就好了。

我的一些参考资料:

* 更新 - 最终版本 *

autoSwitch(): void {
        this.autoPlay = !this.autoPlay;

        if (this.autoPlay) {
            this.autoPlayInter = timer(0, 2000)
                .pipe(
                    takeUntil(this.stopPlay$),
                    tap((_) => (this.toggleMe.checked = !this.toggleMe.checked)),
                )
                .subscribe();
        } else {

            this.stopPlay$.next(); // this stops the timer
        }
    }

你应该改变这个:

const autoPlayInter = interval(1000);
autoPlayInter.subscribe(() => (this.toggleMe.checked = !this.toggleMe.checked));
autoPlayInter.pipe(takeUntil(this.stopPlay$));  

对此:

const autoPlayInter = interval(1000);
autoPlayInter
    .pipe(takeUntil(this.stopPlay$))
    .subscribe(() => (this.toggleMe.checked = !this.toggleMe.checked));

原因: takeUntil 影响订阅者,而不影响来源。

回答更新后的代码:

应更改为如下所示:

autoPlay() {
    this.autoPlay = !this.autoPlay;

    if (this.autoPlay) {
        this.autoPlayInter = interval(2000);
        this.autoPlayInter
            .pipe(takeUntil(this.stopPlay$))
            .subscribe(() => {
                this.examToggle.checked = !this.examToggle.checked;
            });
    } else {
        this.stopPlay$.next();
    }
 }