如何过滤我的 Observable 的值?

How to filter the values of my Observable?

我正在学习 observables atm,我有一个问题。我从我的后端 api 得到一个 json 数组并将它放在一个 Observable 中(其中图像是我自己定义的模型)。现在这些是所有图像,但我只想要名称以显示开头的图像。我已经尝试了一些事情,但找不到解决方案。这就是我到目前为止所得到的。

  get images$(): Observable<Image[]> {
    return this._fetchImages$
      .pipe(
        filter(i => i.filter(img => img.name.toLowerCase().startsWith("display")))
      );
  }

这给出: Type 'Image[]' is not assignable to type 'boolean'.ts(2322) filter.d.ts(3, 46): The expected type comes from the return type of this signature.

图片模型class

export class Image {
  constructor(
    private _name: string,
    private _iso: string,
    private _shutter: string,
    private _aperture: string,
    private _country: string,
    private _likes: number,
    private _content: string
  ) {}

  get name(): string {
    return this._name;
  }

  get iso(): string {
    return this._iso;
  }

  get shutter(): string {
    return this._shutter;
  }

  get aperture(): string {
    return this._aperture;
  }

  get country(): string {
    return this._country;
  }

  get likes(): number {
    return this._likes;
  }

  get content(): string {
    return this._content;
  }

  set likes(value: number) {
    this._likes = value;
  }

  static fromJson(json: any): Image {
    return new Image(
      json.name,
      json.iso,
      json.shutterSpeed,
      json.aperture,
      json.country,
      json.likes,
      json.content
    );
  }
}

为我提供价值的服务

export class ImageDataService {
  constructor(private http: HttpClient) {}

  get images$(): Observable<Image[]> {
    return this.http
      .get(`${environment.apiUrl}/images/`)
      .pipe(map((list: any[]): Image[] => list.map(Image.fromJson)));
  }
}

请求 observable 的组件

export class GridComponent implements OnInit {
  public countryFilter: string;
  public filterImage$ = new Subject<string>();
  private _fetchImages$: Observable<Image[]> = this._imageDataService.images$;

  constructor(private _imageDataService: ImageDataService) {
    this.filterImage$
      .pipe(
        distinctUntilChanged(),
        debounceTime(400),
        map(val => val.toLowerCase())
      )
      .subscribe(val => (this.countryFilter = val));
  }

  get images$(): Observable<Image[]> {
    return this._fetchImages$.pipe(
      map(i => i.filter(img => img.name.toLowerCase().startsWith('display')))
    );
  }

  ngOnInit() {}
}
<div>
  <mat-form-field>
    <input matInput placeholder="Country" type="text" #countryName (keyup)="filterImage$.next($event.target.value)"
      class="browser-default">
  </mat-form-field>
  <mat-grid-list cols="3" gutterSize=" 5px" rowHeight="500px">
    <mat-grid-tile *ngFor="let image of (images$ | async)">
      <app-image [image]="image"></app-image>
    </mat-grid-tile>
  </mat-grid-list>
</div>

export class ImageComponent implements OnInit {
  private _icon: string;
  @Input('image') public image: Image;

  constructor() {
    this._icon = 'favorite_border';
  }

  ngOnInit() {}

  like() {
    if (this._icon === 'favorite_border') {
      this._icon = 'favorite';
      this.likes++;
    } else {
      this._icon = 'favorite_border';
      this.image.likes--;
    }
    console.log(this._icon);
  }

  get icon(): string {
    return this._icon;
  }

  set icon(value: string) {
    this._icon = value;
  }

  get iso(): string {
    return this.image.iso;
  }

  get aperture(): string {
    return this.image.aperture;
  }

  get shutterspeed(): string {
    return this.image.shutter;
  }

  get country(): string {
    return this.image.country;
  }

  get name(): string {
    return this.image.name;
  }

  get content(): string {
    return this.image.content;
  }

  get likes(): number {
    return this.image.likes;
  }

  set likes(value: number) {
    this.image.likes = value;
  }
}

我收到 10 json objects 发送给我:

{
  "id": 1,
  "name": "Header",
  "iso": "ISO-200",
  "shutterSpeed": "1/80 sec",
  "aperture": "f/5.6",
  "country": "Belgium",
  "content": //a base64 string
}
{
  "id": 2,
  "name": "Parallax1",
  "iso": "ISO-100",
  "shutterSpeed": "1/200 sec",
  "aperture": "f/10",
  "country": "Italy",
  "content": another base64 string
}
{
  "id": 5,
  "name": "Display1",
  "iso": "ISO-100",
  "shutterSpeed": "1/200 sec",
  "aperture": "f/10",
  "country": "Italy",
  "content": another base64 string
}

现在图像之间的主要区别在于名称: 我有 1 header、3 个视差和 6 个显示图像。我现在想过滤那些我只得到显示图像的东西。基本上:输入 10 张图像 ---> 输出 6 张

亲切的问候

我认为您应该将 filter 更改为 map,如下所示:

.pipe(
    map(
        i => i.filter(
            img => img.name.toLowerCase().startsWith("display")
        )
    )
);

我已将映射移动到 class,在那里我使用 HttpClient 获取它们,而不是尝试在我的组件中过滤它们。它现在可以在没有查询字符串的情况下工作。

代码:

export class ImageDataService {
  constructor(private http: HttpClient) {}

  get images$(): Observable<Image[]> {
    return this.http
      .get(`${environment.apiUrl}/images/`)
      .pipe(
        map((list: any[]): Image[] => list.map(Image.fromJson)),
        map(imgs =>
          imgs.filter(img => img.name.toLowerCase().startsWith('display'))
        )
      );
  }
}