RxJS - 管道 observable re-运行 过于频繁
RxJS - Piped observable re-running too often
单击按钮后,我想切换到我的 file$ observable,检查它是否已填充,并使用它上传 uploadRates(file, date)
中的文件。
const click$ = Observable.fromEvent(this.uploadButton.nativeElement, 'click').pipe(
switchMapTo(this.file$),
filter(file => !!file && !!this.dateForRates),
tap(_ => this.isLoading$.next(true)),
exhaustMap(file => this.uploadRates(file, this.dateForRates))
).subscribe({
next: x => {
this.handleUploadRatesResult(x);
this.isLoading$.next(false);
},
complete: () => {
console.log('complete');
this.isLoading$.next(false);
},
error: err => {
console.log(err);
this.isLoading$.next(false);
}
});
它有效,但我只是不想在代码中的其他地方执行类似 this.file$.next(undefined);
的操作时重新 运行 任何管道,它确实如此。单击按钮时,我只希望它为 运行。如何使 ngOnInit
中的管道仅在单击按钮时重新 运行,但仍然从我的 file$
变量中提取文件以检查它是否已填充并在单击时上传按钮?
我认为问题是 file$
在发出一个值后没有完成。这意味着内部订阅将保持活动状态。
你可以做的是添加一个 take(1)
以确保它在第一个发出的值之后不再被订阅:
switchMapTo(this.file$.pipe(take(1))),
您也可以使用 withLatestFrom
运算符。它将订阅给定的可观察值并存储最新值,但如果可观察值本身发出则不会发出:
const click$ = Observable.fromEvent(this.uploadButton.nativeElement, 'click').pipe(
withLatestFrom(this.file$),
map(([_, file]) => file),
filter(file => !!file && !!this.dateForRates),
tap(_ => this.isLoading$.next(true)),
exhaustMap(file => this.uploadRates(file, this.dateForRates))
).subscribe({
next: x => {
this.handleUploadRatesResult(x);
this.isLoading$.next(false);
},
complete: () => {
console.log('complete');
this.isLoading$.next(false);
},
error: err => {
console.log(err);
this.isLoading$.next(false);
}
});
我通常不会容忍使用 RxJS BehaviorSubject
s value
getter。它可用于同步获取可观察对象持有的当前值。但在这种情况下,可以利用它来避免订阅可观察对象。尝试以下
const click$ = Observable.fromEvent(this.uploadButton.nativeElement, 'click').pipe(
map(() => this.file$.value), // <-- use the `value` getter here
filter(file => !!file && !!this.dateForRates),
tap(_ => this.isLoading$.next(true)),
exhaustMap(file => this.uploadRates(file, this.dateForRates))
).subscribe({
...
单击按钮后,我想切换到我的 file$ observable,检查它是否已填充,并使用它上传 uploadRates(file, date)
中的文件。
const click$ = Observable.fromEvent(this.uploadButton.nativeElement, 'click').pipe(
switchMapTo(this.file$),
filter(file => !!file && !!this.dateForRates),
tap(_ => this.isLoading$.next(true)),
exhaustMap(file => this.uploadRates(file, this.dateForRates))
).subscribe({
next: x => {
this.handleUploadRatesResult(x);
this.isLoading$.next(false);
},
complete: () => {
console.log('complete');
this.isLoading$.next(false);
},
error: err => {
console.log(err);
this.isLoading$.next(false);
}
});
它有效,但我只是不想在代码中的其他地方执行类似 this.file$.next(undefined);
的操作时重新 运行 任何管道,它确实如此。单击按钮时,我只希望它为 运行。如何使 ngOnInit
中的管道仅在单击按钮时重新 运行,但仍然从我的 file$
变量中提取文件以检查它是否已填充并在单击时上传按钮?
我认为问题是 file$
在发出一个值后没有完成。这意味着内部订阅将保持活动状态。
你可以做的是添加一个 take(1)
以确保它在第一个发出的值之后不再被订阅:
switchMapTo(this.file$.pipe(take(1))),
您也可以使用 withLatestFrom
运算符。它将订阅给定的可观察值并存储最新值,但如果可观察值本身发出则不会发出:
const click$ = Observable.fromEvent(this.uploadButton.nativeElement, 'click').pipe(
withLatestFrom(this.file$),
map(([_, file]) => file),
filter(file => !!file && !!this.dateForRates),
tap(_ => this.isLoading$.next(true)),
exhaustMap(file => this.uploadRates(file, this.dateForRates))
).subscribe({
next: x => {
this.handleUploadRatesResult(x);
this.isLoading$.next(false);
},
complete: () => {
console.log('complete');
this.isLoading$.next(false);
},
error: err => {
console.log(err);
this.isLoading$.next(false);
}
});
我通常不会容忍使用 RxJS BehaviorSubject
s value
getter。它可用于同步获取可观察对象持有的当前值。但在这种情况下,可以利用它来避免订阅可观察对象。尝试以下
const click$ = Observable.fromEvent(this.uploadButton.nativeElement, 'click').pipe(
map(() => this.file$.value), // <-- use the `value` getter here
filter(file => !!file && !!this.dateForRates),
tap(_ => this.isLoading$.next(true)),
exhaustMap(file => this.uploadRates(file, this.dateForRates))
).subscribe({
...