【问题标题】:What's the correct way and place to share observable data共享可观察数据的正确方式和地点是什么
【发布时间】:2019-04-30 16:09:27
【问题描述】:

我有 2 个组件和一个提供 observable 的服务。这两个组件都是延迟加载的模块。

服务:

this.filteredBookings$ = this._filteredBookings
  .asObservable()
  .pipe(
    tap(s => {
      console.log(s, 'activity');
      return s;
    })
  );

我已在此处添加点击以查看任何订阅活动。

组件 1:

this.bookings$ = this._bookingService.filteredBookings$;

this.sum$ = this.bookings$.pipe(
  map(bookings => bookings
    .map(booking => booking.value)
    .reduce((total, value) => total + value, 0)
  )
);

组件 1 模板:

<ion-list *ngIf="bookings$ | async; let bookings; else loading">
    ...
    <ion-label slot="end" text-right>
        <ion-text color="medium"><b>{{ sum$ | async }}</b></ion-text>
    </ion-label>
</ion-list>
...

组件 2:

this.bookings$ = this._bookingService.filteredBookings$;

我想防止不必要的订阅。当我正确理解它时,组件 1 中的两个可观察对象订阅了服务提供的可观察对象。组件 1 模板中的异步管道也订阅了这个 observable。那么有 4 个订阅 / 3 个不必要的订阅?

为了防止不必要的,我找到了 share()。

this.filteredBookings$ = this._filteredBookings
  .asObservable()
  .pipe(
    share()
  );

我认为不需要 sharereplay,因为 _filteredBookings 是一个始终缓存最后一个值的 BehaviorSubject。

文档说:

“只要有至少一个订阅者,这个 Observable 就会被订阅并发出数据。当所有订阅者都取消订阅后,它将取消订阅源 Observable。”

所以当我切换路由并加载组件 2 时,我担心服务中的 observable 会被取消?因为组件 1 的 observable 在组件 2 可以订阅之前取消订阅(异步管道处理取消订阅?)?

我该如何处理?

【问题讨论】:

    标签: angular rxjs6


    【解决方案1】:

    我在服务中是这样完成的:

    private productsUrl = 'api/products';
    private products: IProduct[];
    
    private selectedProductSource = new BehaviorSubject<IProduct | null>(null);
    selectedProductChanges$ = this.selectedProductSource.asObservable();
    
    constructor(private http: HttpClient) { }
    
    changeSelectedProduct(selectedProduct: IProduct | null): void {
        this.selectedProductSource.next(selectedProduct);
    }
    
    getProducts(): Observable<IProduct[]> {
        if (this.products) {
            return of(this.products);
        }
        return this.http.get<IProduct[]>(this.productsUrl)
                        .pipe(
                            tap(data => console.log(JSON.stringify(data))),
                            tap(data => this.products = data),
                            catchError(this.handleError)
                        );
    }
    

    这是我的例子:https://github.com/DeborahK/Angular-Communication/tree/master/APM-Final

    我不明白“防止不必要的订阅”的问题?

    如果您想要更正式的模式,可以查看 NgRx。我在这里有一个例子:https://github.com/DeborahK/Angular-NgRx-GettingStarted

    【讨论】:

      猜你喜欢
      • 2020-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-06
      • 2021-07-29
      • 2021-12-06
      • 2011-01-04
      • 2022-01-10
      相关资源
      最近更新 更多