Как бороться с необязательным аргументом для наблюдаемого? - PullRequest
0 голосов
/ 12 июня 2018

У меня есть угловой компонент, который извлекает данные из службы с 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);
  }
}

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Проблема в том, что вы используете 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);
 }
}

Вот стэк-блиц, с которым вы можете играть: https://stackblitz.com/edit/angular-ce8jrw

РЕДАКТИРОВАТЬ: я не могу объяснить, почему Subject не сработал, как я пытался this.filter$.next(null) в constructor.

0 голосов
/ 12 июня 2018

Я не на 100% здесь, но я считаю, что, поскольку вы не подписаны на фильтр явно, вы не можете эффективно отслеживать его изменения.Я бы добавил

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

Это должно прослушать создание фильтра и затем запустить this.service.getItems(filter)

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...