RxJS Observable合并角度

时间:2017-04-07 13:52:13

标签: javascript angular rxjs observable

我有一个订阅消息流的沙箱,我想过滤该流以查找使用另一个组件中指定的路由参数发送到特定用户或从特定用户接收的消息。

messages.sandbox.ts:

messages$: Observable<Array<Message>> = this.store.select(state => state.data.messages);    

fetchReceived(id: string): Observable<Array<Message>> {
    return this.messages$.map((messages: any) => {
        return messages.filter((message: Message) => {
            return message.recipientId == id;
        });

    });
}

fetchSent(id: string): Observable<Array<Message>> {
    return this.messages$.map((messages: any) => {
        return messages.filter((message: Message) => {
            return message.userId == id;
        })
    })
}

messages.detail.container.ts

sentMessages$ = new Observable<Array<Message>>();
receivedMessages$ = new Observable<Array<Message>>();
matchingMessages$ = new Observable<Array<Message>>();



ngOnInit() {

    this.route.params.subscribe((params: Params) => {
        this.sentMessages$ = this.sb.fetchReceived(params['id']);
        this.receivedMessages$ = this.sb.fetchSent(params['id']);

        this.matchingMessages$ = Observable.merge(this.sentMessages$, this.receivedMessages$);

    });
}

this.matchingMessages $似乎只包含this.receivedMessages $但是我知道this.sentMessages $不是null,因为我可以在我的模板中使用它而没有问题。

我是否遗漏了合并Observable的内容?创建一个fetchMessages方法可以更好地过滤userId或recipientId等于route param id吗?如果是这样,我该怎么做?

谢谢!

1 个答案:

答案 0 :(得分:0)

你有正确的总体思路。只是一些缺陷。

  1. 永远不要使用new Observable<T>()。它没有做你认为它做的事情。它几乎没有做任何有用的事情。始终从工厂方法或其他可观察对象构建可观察对象
  2. 您需要使用运算符将​​params observable转换为新的observable。您的问题是订阅到params observable,然后每次都构造新的observable。但是其他代码已经订阅了初始的observable,所以他们永远不会看到这些变化。
  3. 所以你想做这样的事情:

    sentMessages$ : Observable<Array<Message>>;
    receivedMessages$ : Observable<Array<Message>>;
    matchingMessages$ : Observable<Array<Message>>;
    
    ngOnInit() {
        const params$ = this.route.params;
    
        // use switchMap to map the new params to a new sent observable
        // each time params change, unsubscribe from the old fetch and subscribe
        // to the new fetch.  Anyone subscribed to "sentMessages" will see the
        // change transparently
        this.sentMessages$ = params$.switchMap((params: Params) => this.sb.fetchReceived(params['id']));
        // same for received
        this.receivedMessages$ = params$.switchMap((params: Params) => this.sb.fetchSent(params['id'])));
    
        // merge the 2 streams together
        this.matchingMessages$ = Observable.merge(this.sentMessages$, this.receivedMessages$);
    }
    

    编辑:

    回答你的另一个问题:创建一个匹配发件人和收件人的单一observable是否更好:取决于你的用例。但是你可以这样做:

    messages.sandbox.ts:

    fetchEither(id: string): Observable<Array<Message>> {
        return this.messages$.map((messages: any) => {
            return messages.filter((message: Message) => {
                return message.recipientId == id || message.userId === id;
            });
    
        });
    }
    

    容器:

    matchingMessages$ : Observable<Array<Message>>;
    
    ngOnInit() {
        const params$ = this.route.params;
    
        // use switchMap to map the new params to a new either observable
        // each time params change, unsubscribe from the old and subscribe
        // to the new fetch.  Anyone subscribed to "matchingMessages" will see the
        // change transparently
        this.matchingMessages$ = params$.switchMap((params: Params) => this.sb.fetchEither(params['id']));
    }