用户单击按钮时刷新可观察的数据

时间:2019-04-02 06:55:14

标签: angular rxjs

我有一个Angular 6组件,其中有一个使用异步管道订阅可观察项的网格。我想要一个按钮,当单击该按钮时,将刷新该可观察数据。我添加了以下代码:

public refreshData(): void {
   this.details$ = this._service.getDetails();
}

然后,在模板上:

*ngIf="(details$ | async); let d"

现在,每当用户单击按钮时,都会执行refreshData方法。该代码有效,刷新了数据,但我为每次单击创建了一个新的可观察对象。 有更好的方法来解决这个问题吗?

3 个答案:

答案 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();