Angular RxJS过滤器 - 返回一个空的或填充的Observable列表

时间:2018-06-17 21:06:33

标签: angular rxjs6

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

// 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数组过滤器,如果没有则返回空数组)匹配,但总是返回一个对象。)
  3. 以下是StackBlitz的示例: https://stackblitz.com/edit/cookies-bakery

1 个答案:

答案 0 :(得分: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

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