【问题标题】:Angular RxJS filter - Return an empty or populated Observable listAngular RxJS 过滤器 - 返回一个空的或填充的 Observable 列表
【发布时间】:2018-11-26 18:26:40
【问题描述】:

在“搜索”服务方法中,我返回名称中包含搜索关键字的项目:

// data.service.ts
import { Injectable } from '@angular/core';
import { Observable, pipe, of } from 'rxjs';
import { map, filter, flatMap  } from 'rxjs/operators';
import { Goodie } from './models/Goodie';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  public goodies = [
    { name: 'Brownie Pillow Cookie'},
    { name: 'Talenti Pistachio' },
    { name: 'SnickerDoodle' }
];
  constructor() {}

  public getGoodies(): Observable<Goodie[]> {
    return of(this.goodies);
  }

  public search(keyword): Observable<Goodie> {
    return this.getGoodies().pipe(
      flatMap(data => data),
      filter(g => g.name.toLowerCase().includes(keyword.toLowerCase()))
    );
  }
}

当名称上有关键字匹配时,这有效(返回项目)。例如,搜索“e”返回结果,我可以看到显示在控制台中:

// app.component.ts
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { DataService } from './data.service';
import { Goodie } from './models/Goodie';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  public searchResult: Goodie[] = [];

  constructor(private storeService: DataService) {}

  handleSearch(type, keyword) {
      this.searchResult = [];
      this.storeService.search(keyword).subscribe(data => {
      console.log('-----------');
      this.searchResult.push(data);
      console.log(this.searchResult);
      console.log('-----------');
    });
  }
}

但是,如果我搜索与任何项目都不匹配的关键字,例如“x”,那么不仅不会返回任何结果,而且不会从 this.storeService.search(keyword) 内部记录任何内容。 subscribe 方法 - 控制台甚至不打印语句 console.log('-----------')。

因此,我希望澄清两件事:

  1. 如果 rxjs 操作没有为过滤器产生结果,handleSearch 订阅方法的主体是否也会运行?
  2. 什么是推荐的方法来让它工作,以便 tthis.storeService.search(keyword).subscribe 总是返回结果,即使它是一个空列表(类似于 es6 数组过滤器,如果没有则返回一个空数组匹配,但始终返回一个对象)。

这是 StackBlitz 上的示例: https://stackblitz.com/edit/cookies-bakery

【问题讨论】:

  • 我会推荐使用array.filter 函数而不是可观察的过滤器函数,毕竟,你想从它的声音中过滤数组而不是可观察的流。 stackblitz.com/edit/…

标签: angular rxjs6


【解决方案1】:

正如@user184994 所说,使用普通的旧 array.filter 来获取结果。

正如您所猜测的,当搜索不匹配时,单个项目的可观察对象(与数组的可观察对象相比)不会发出任何内容。

这修复了您的示例代码,

public search(keyword): Observable<Goodie[]> {
  // return this.getGoodies().pipe(
  //   flatMap(data => data),
  //   filter(g => g.name.toLowerCase().includes(keyword.toLowerCase()))
  // );
  return of(
    this.goodies.filter(g => 
      g.name.toLowerCase().includes(keyword.toLowerCase())
    )
  );
}

但是,如果您绝对需要组件中的单个项目流,则可以在未找到任何内容时从搜索中发出错误,并在订阅中捕获它。

public search(keyword): Observable<Goodie> {
  const results = this.goodies.filter(g => 
    g.name.toLowerCase().includes(keyword.toLowerCase())
  );
  return results.length ? from(results) : throwError("Not found"); 
}


handleSearch(keyword) {
  this.searchResult = [];
  this.storeService.search(keyword).subscribe(
    data => {
      console.log('-----------');
      this.searchResult.push(data);
      console.log(this.searchResult);
      console.log('-----------');
    },
    err => this.err = err
  );
}

这里是修改后的StackBlitz


或者,如果您不喜欢在逻辑中使用错误处理,您的服务可以发出一个可观察的结果计数,可以在组件中单独订阅。

【讨论】:

    猜你喜欢
    • 2018-12-28
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多