如何处理可观察对象的可选参数?

How to deal with an optional argument to an observable?

我有一个 Angular 组件,它使用 service.getItems 从服务中获取数据。有时,服务调用很简单,而在其他情况下,则需要过滤器。这个过滤器可以通过组件 属性 filter.

来设置

我确信我从根本上遗漏了一些东西,但我无法让它正常工作。我要么让它接受过滤器,要么忽略过滤器,但不对过滤器的存在做出反应。

有什么建议可以修改下面的代码以实际工作吗?

@Component({}
  selector: 'my-component',
  template: `
    <!-- Items are shown async -->
    {{ items | async }}
  `
})
export class MyComponent {

  //////////////////////////////////////////////////////////////////
  // Initialize the filter observable with a null value
  //////////////////////////////////////////////////////////////////
  constructor(private service) {
    this.filter = null;
  }

  //////////////////////////////////////////////////////////////////
  // Filter observable to hookup the filter value to the service
  //////////////////////////////////////////////////////////////////
  filter$: Subject<Filter> = new Subject<Filter>();

  //////////////////////////////////////////////////////////////////
  // Service call to fetch items
  //////////////////////////////////////////////////////////////////
  items$: Observable<any[]> = this.filters$.pipe(
    switchMap(filter => this.service.getItems(filter));
  );

  //////////////////////////////////////////////////////////////////
  // Allow filter with
  // <my-component [filter]="myFilter">
  //////////////////////////////////////////////////////////////////
  @Input()
  set filter(filter: Filter) {
    this.filter$.next(filter);
  }
}

我在这里不是 100%,但我相信因为您没有明确订阅过滤器,所以您无法有效地观察它的变化。我会添加

this.filters$.subscribe( res => {
  res.pipe(
    switchMap(filter => this.service.getItems(filter)
  )
})

这应该监听过滤器的创建然后触发 this.service.getItems(filter)

祝你好运!

问题是因为您使用的是 Subject 而不是 BehaviorSubject。如果您希望 filter$ 在初始化时发出空值,则需要使用 BehaviorSubject。截至您将 items$ 分配给 Observable 的那一刻,this.filter$ 还没有发射任何东西,所以整个 Observable 还没有 运行。

@Component({
  selector: 'my-component',
  template: `
       <!-- Items are shown async -->
       {{ items$ | async }}
  `
})
export class MyComponent {

 //////////////////////////////////////////////////////////////////
 // Initialize the filter observable with a null value
 //////////////////////////////////////////////////////////////////
 constructor(private service) {
 }

 //////////////////////////////////////////////////////////////////
 // Filter observable to hookup the filter value to the service
 //////////////////////////////////////////////////////////////////
 filter$: BehaviorSubject<Filter> = new BehaviorSubject<Filter>(null);

 //////////////////////////////////////////////////////////////////
 // Service call to fetch items
 //////////////////////////////////////////////////////////////////
 items$: Observable<any[]> = this.filters$.pipe(
   switchMap(filter => this.service.getItems(filter));
 );

 //////////////////////////////////////////////////////////////////
 // Allow filter with
 // <my-component [filter]="myFilter">
 //////////////////////////////////////////////////////////////////
 @Input()
 set filter(filter: Filter) {
   this.filter$.next(filter);
 }
}

这里有一个你可以玩的 stackblitz:https://stackblitz.com/edit/angular-ce8jrw

编辑:我无法解释为什么 Subject 不起作用,因为我也在 constructor 中尝试了 this.filter$.next(null)