【问题标题】:filtering an array of observables efficiently有效地过滤一组可观察对象
【发布时间】:2019-09-26 12:12:47
【问题描述】:

我正在学习官方 Angular 教程 (https://angular.io/tutorial/toh-pt4)。对不起我的水平低:(

我正在尝试修改一个返回英雄列表的服务...作为 rxjs 的 observables 对象,因为这是最有效的方法

hero.service.ts
==============

import {Injectable} from '@ angular / core';

import {Observable, of} from 'rxjs';

import {Hero} from './hero';
import {HEROES} from './mock-heroes';
import {MessageService} from './message.service';

@Injectable ({
  providedIn: 'root',
})
export class HeroService {

  constructor (private messageService: MessageService) {}

  getHeroes (): Observable <Hero []> {
    // TODO: send the message _after_ fetching the heroes
    this.messageService.add ('HeroService: fetched heroes');
    return of (HEROES);
  }
}

mock-heroes
===========

import {Hero} from './hero';

export const HEROES: Hero [] = [
  {id: 11, name: 'Mr. Nice '},
  {id: 12, name: 'Narco'},
  {id: 13, name: 'Bombast'},
  {id: 14, name: 'Celeritas'},
  {id: 15, name: 'Magneta'},
  {id: 16, name: 'RubberMan'},
  {id: 17, name: 'Dynama'},
  {id: 18, name: 'Dr IQ'},
  {id: 19, name: 'Magma'},
  {id: 20, name: 'Tornado'}
];

我想要一个服务,当我传递一个 id 时只返回一个英雄

import {Injectable} from '@ angular / core';
import {Hero} from './hero';
import {HEROES} from './mock-heroes';
import {Observable, of} from 'rxjs';
import {MessageService} from './message.service';
import {map} from 'rxjs / operators';

@Injectable ({
  providedIn: 'root'
})
export class HeroService {

  private heroes: Observable <Hero []>;

  getHeroes (): Observable <Hero []> {
    this.messageService.add ('HeroService: fetched heroes');
    // return of (HEROES);
    this.heroes = of (HEROES);
    return this.heroes;
  }

  getHeroeById (id: number): Observable <Hero> {
    this.messageService.add ('A hero is queried with id' + id);
    

    return this.heroes.pipe (map (x => x.id === id));
  }

  constructor (private messageService: MessageService) {}

 / * getHeroes (): Hero [] {
    return HEROES;
  } * /

  //builder() { }
}

src / app / hero.service.ts (26,5) 中的错误:错误 TS2322:类型“Observable”不可分配给类型“Observable”。 类型“布尔”不能分配给类型“英雄”。 src/app/hero.service.ts (26.40): TS2339 错误: 属性 'id' 在类型'Hero []' 上不存在。

你能帮帮我吗?

【问题讨论】:

    标签: angular rxjs rxjs6


    【解决方案1】:

    您有几个选择。您可以使用 Array.find() 或 Array.filter()

    Array.filter()

    getHeroeById (id: number): Observable <Hero> {
      this.messageService.add('A hero is queried with id: ' + id);
    
      // Filter heroes to get heroById
      return this.heroes.filter(x => x.id == id)[0];
    }
    

    Array.find()

    getHeroeById (id: number): Observable <Hero> {
      this.messageService.add('A hero is queried with id: ' + id);
    
      // Find hero by Id.
      return this.heroes.find(x => x.id == this.personId);
    }
    

    【讨论】:

    • 你应该使用find,因为它会在找到第一个id时返回英雄。过滤器将遍历所有英雄,并将 id 与您的 id 进行比较,即使它可以在位置一找到英雄。简而言之,find 将在条件匹配后立即返回。
    【解决方案2】:

    你想返回英雄列表中匹配id的英雄,尝试替换

    return this.heroes.pipe (map (x => x.id === id));
    

    通过

    return this.heroes.pipe (map (heroes => heroes.find( hero => hero.id === id));
    

    【讨论】:

      【解决方案3】:

      你的问题是这一行:

      return this.heroes.pipe (map (x => x.id === id));
      

      您正在使用 rx map 操作符,它对流中的项目进行操作和转换,而流中的项目是实际的英雄数组。您正在返回数组的某些不存在的 id 属性是否等于 id 参数(一个布尔值)的测试结果。这就是您看到错误的原因。

      在这种情况下,您应该在流中的数组上使用数组查找运算符,因为您想在数组中查找该项目,如下所示:

      return this.heroes.pipe (map (heroes => heroes.find(h => h.id === id)));
      

      这样,您将在 rx 映射变换操作中返回数组查找操作的实际结果。

      接下来,在调用 getHeroes() 之前,不要初始化 heroes obersvable。这可能是故意的,但您似乎应该在构造函数中执行此操作,以便可以安全地首先调用 getHeroeById()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-11-23
        • 2023-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多