我有一个Angular 6组件,其中有一个使用异步管道订阅可观察项的网格。我想要一个按钮,当单击该按钮时,将刷新该可观察数据。我添加了以下代码:
public refreshData(): void {
this.details$ = this._service.getDetails();
}
然后,在模板上:
*ngIf="(details$ | async); let d"
现在,每当用户单击按钮时,都会执行refreshData方法。该代码有效,刷新了数据,但我为每次单击创建了一个新的可观察对象。 有更好的方法来解决这个问题吗?
答案 0 :(得分:2)
如前所述,一种更具反应性的方式如下:
import {Subject,Observable} from 'rxjs';
import {startWith,switchMap} from 'rxjs/operators';
class FooComponent implements OnDestroy {
private readonly refreshClick$ = new Subject<void>();
readonly details$ : Observable<FooDetails>;
constructor(...){
this.details$ = this.refreshClick$.pipe(
// fake emission of a click so that initial data can be loaded
startWith(undefined),
switchMap(() => this._service.getDetails())
);
}
ngOnDestroy(){
// "complete" should be invoked on subjects once their lifetime is complete
refreshClick$.complete();
}
refresh(){
this.refreshClick$.next();
}
}
答案 1 :(得分:0)
尝试使用主题,每次您要更新数据时,只需更新主题,它就会反映在ui中。
答案 2 :(得分:-1)
我不确定您的目标是什么。若要仅在单击按钮时更新视图中的数据,即使该服务在此期间提供了新鲜的数据,还是仅在单击按钮时向流中添加一些全新的Details对象,但是视图应连续更新它们的详细信息来自服务或按钮单击。现在假设第二种情况:
要控制要添加到流中的流的流,可以使用Subject
。
假设您不想触碰_service
逻辑,只需要在组件内部刷新值,但是仍然可以从其getDetails()
观察到输入:您可以在以下位置订阅服务您的ngOnInit
,将结果传递到您的本地Subject
,还将刷新后的值传递到您的refreshData()
方法中。假设详细信息的类型为Details
,我们得到:
private details$: Subject<Details>;
constructor(private _service: Service) {}
ngOnInit(): void {
this._service.getDetails().subscribe(updateDetails => this.details$.next(updateDetails));
}
ngOnDestroy(): void {
this.details$.complete();
}
public refreshData(): void {
this.details$.next(new Details());
}
如果不仅要在本地保留更新,还要将更新发送给服务,则必须调整服务逻辑以处理详细信息的更新。这意味着将可观察的服务转换为Subject
。通常,您不想直接公开服务主题,而只公开主题的可观察的一面,并在方法中处理更新请求。这意味着在您的服务中:
private _detailsSource$: Subject<Details> = new Subject<Details>();
private _details$: Observable<Details> = this._detailsSource$.asObservable();
public getDetails(): Observable<Details> {
return this._details$;
}
public updateDetails(update: Details): void {
// you can add some check logic if the update is valid here
this._detailsSource$.next(update);
}
在您的组件中,您只需要调整刷新方法:
refreshData(): void {
this._service.updateDetails(new Details());
}
您还可以跳过服务中的getDetails
方法,只需公开即可看到的细节即可。
private _detailsSource$: Subject<Details> = new Subject<Details>();
public details$: Observable<Details> = this._detailsSource$.asObservable();