Nilesh Patel 提供的答案应该可以正常工作,但我仍然想添加此答案以分享您可能需要在应用中使用的一些小技巧和改进。
请看一下这个Stackblitz demo。
首先要注意的是,如果您正在使用 timer 运算符,并且您有兴趣在它第一次发出时做某事,您可以检查该运算符返回的值,看看它是否是 0 :
timer(0, 10000).pipe(
tap(currentTimer => {
if (currentTimer === 0) {
this.someFunctionToRunOnlyOnce();
}
}),
// ...
);
要记住的第二件事是,您可以创建一个主题并像这样使用takeUntil 运算符,而不是将每个订阅都存储在一个变量中(然后取消所有订阅):
private unsubscribe$: Subject<void> = new Subject<void>();
// ...
timer(0, 10000).pipe(
// ... other operators
takeUntil(this.unsubscribe$) // <-- like this
).subscribe();
// ...
ngOnDestroy() {
this.unsubscribe$.next(); // <-- this will clean the streams
this.unsubscribe$.unsubscribe(); // <-- this will clean the unsubscribe$ stream
}
要记住的另一件非常小的事情是,您可以随时“暂停”和“恢复”流,而不会“破坏”它。例如,您可以在离开页面时暂停它,然后在用户即将再次进入页面时使用filter 运算符再次恢复:
private isInPage: boolean = true;
// ...
timer(0, 10000).pipe(
filter(() => this.isInPage),
// other operators ...
);
// ...
ionViewWillEnter() {
this.isInPage = true;
}
ionViewWillLeave() {
this.isInPage = false;
}
所以把所有这些放在一起,它会是这样的:
import { Component, OnInit } from "@angular/core";
import { NavController } from "@ionic/angular";
import { Observable, of, Subject, timer } from "rxjs";
import { delay, filter, switchMap, takeUntil, tap } from "rxjs/operators";
@Component({
selector: "app-home",
templateUrl: "./home.page.html",
styleUrls: ["./home.page.scss"]
})
export class HomePage implements OnInit {
private isInPage: boolean = true;
private unsubscribe$: Subject<void> = new Subject<void>();
constructor(private navCtrl: NavController) {}
ngOnInit() {
timer(0, 10000)
.pipe(
filter(() => this.isInPage),
tap(currentTimer => {
if (currentTimer === 0) {
this.someFunctionToRunOnlyOnce();
}
}),
switchMap(() => {
return this.someAsynFunction();
}),
takeUntil(this.unsubscribe$)
)
.subscribe();
}
ionViewWillEnter() {
this.isInPage = true;
}
ionViewWillLeave() {
this.isInPage = false;
}
ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.unsubscribe();
}
public openDetailsPage(): void {
this.navCtrl.navigateForward("details");
}
private someAsynFunction(): Observable<number> {
const randomNumber = Math.floor(Math.random() * 10000) + 1;
console.log("==> Running someAsynFunction method");
return of(randomNumber).pipe(delay(1000));
}
private someFunctionToRunOnlyOnce(): void {
console.log("==> Running someAsynFunctionToRunOnlyOnce method");
}
}