【问题标题】:Filter Observable<T[]> to get a specific Observable<T> in RxJS在 RxJS 中过滤 Observable<T[]> 以获取特定的 Observable<T>
【发布时间】:2017-04-21 11:24:39
【问题描述】:

为了学习 Angular,我模拟了一个做两件事的网络服务:

  1. 返回一个数组的 Observable (Observable&lt;T[]&gt;)
  2. 将由 ID 标识为 Observable (Observable&lt;T&gt;) 的项目返回

我就是这样实现的:

export class Event {
    constructor(public id: number, public title: string) {}
}

const EVENTS = [
    new Event(1, 'Tooth extraction'),
    new Event(2, 'English lesson'),
    new Event(3, 'Driving lesson'),
    new Event(4, 'Mortgage meeting'),
];

let eventsObservable: Observable<Event[]> = Observable.of(EVENTS);

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

@Injectable()
export class EventsService {

    getEvents() {
        return eventsObservable;
    }

    getEvent(id: number|string) {
        return eventsObservable.concatMap((x) => {
           return x;
        }).filter((event: Event) => {
            return id === event.id;
        });
    };
}

我只是从 Observable 和 Angular 开始,但是,我不认为我对 getEvent(id: number|string) 的实现是最佳的,因为我正在做的是:

  1. 拍下Observable&lt;T[]&gt;中的每一项,
  2. 每个发送为Observable&lt;T&gt;
  3. 然后才过滤发出的项目以找到我正在寻找的项目,
  4. 将此项目作为 Observable 返回。

有没有更好、更优化的方式从Observable&lt;T[]&gt; 返回一个独特的项目?

【问题讨论】:

  • 为什么不只是return Observable.from(EVENTS.filter(e =&gt; e.id === id)))

标签: angular rxjs observable


【解决方案1】:

有没有更好、更优化的方法来从 Observable 返回一个独特的项目?

使用map,它接受一个可观察对象并根据传递给函数的逻辑返回一个新的可观察对象。

getEvent(id: number | string) : Observable<Event> {
    return eventsObservable.map((x:Event[]):Event => {
        return x.find(y => y.id === id);
    });
};

【讨论】:

    【解决方案2】:

    您实际上根本不需要为此使用 RxJS,但我猜您正在使用 Observables,因为稍后会附加一些其他功能。

    我认为让这个更具可读性的唯一方法是不使用 Observable.of() 来重新发送值,而是使用 Observable.from() 来迭代数组并将每个值作为单独的项目发出。

    let eventsObservable: Observable<Event> = Observable.from(EVENTS);
    
    ...
    
    getEvent(id: number|string) {
        return eventsObservable
          .filter((event: Event) => {
              return id === event.id;
          });
    }
    

    最终,如果您需要将事件作为数组保存在 Observable&lt;Event[]&gt; 中,您可以使用 concatAll 将其展平,这样更容易理解。

    getEvent(id: number|string) {
        return eventsObservable
          .concatAll()
          .filter((event: Event) => {
              return id === event.id;
          });
    };
    

    concatAll() 运算符将Observable&lt;Event[]&gt; 转换为Observable&lt;Event&gt;

    【讨论】:

      【解决方案3】:

      您真正想要的可以通过这种方式完成:

      getEvent(id: number|string) {
              return eventsObservable.flatMap((x) => Observable.from(x)).filter((event: Event) => {
                  return id === event.id;
              });
          };
      

      但请注意,您可以按照@Igor 的建议只使用.map(array=&gt;array.find(...)) 并避免对数组进行不必要的迭代,但这并没有多大意义。

      【讨论】:

        猜你喜欢
        • 2019-08-05
        • 2016-07-01
        • 2019-08-24
        • 1970-01-01
        • 2017-12-29
        • 1970-01-01
        • 2017-08-19
        • 1970-01-01
        • 2016-11-05
        相关资源
        最近更新 更多