【问题标题】:how to concat an observable properly如何正确连接可观察对象
【发布时间】:2018-05-09 02:28:19
【问题描述】:

从我的组件开始,我声明了 observable...

import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import { tap, map, concat } from 'rxjs/operators';

contactsDataSource$: Observable<any>;

然后我将流分配给来自 http 服务的 observable:

this.contactsDataSource$ = this.medialistsrv.getMediaListBuilderData({
    mediaListId: this.mediaListId,
    sortType: this.sortType,
    startRow: this.startRow,
    numRows: this.numRows
}).pipe(
    tap(response => {
        this.mediaList = response
            .filter(items => items.inMediaList === true)
            .map(items => items.contactId);
        this.mediaList.forEach(id => {
            this._contacts.push(this.fb.control(id));
        });
    }),
    map(response => response)
);

并使用异步管道将其引入模板:

<div *ngIf="(contactsDataSource$ | async) as contactList; else loading">

稍后在模板中我介绍了一种加载更多结果的方法。这是我需要连接到初始流的地方

increment() {
    this.contactsDataSource$.concat(
        this.medialistsrv.getMediaListBuilderData({
            mediaListId: this.mediaListId,
            sortType: this.sortType,
            startRow: (this.numRows + 1),
            numRows: (this.numRows * 2)
        }).map(response => response)
    );
}

运行此程序时,我在控制台中收到一条错误消息:

ng:///MediaListModule/MediaListBuilderComponent.ngfactory.js:351 ERROR TypeError: this.contactsDataSource$.concat is not a function

我还在 rxjs 学习悬崖上,所以显然我不明白如何正确地做到这一点。我在这里错过了什么?

【问题讨论】:

  • 您正在混合使用 pipable 和“原型”运算符。使用this.contactsDataSource$.pipe(concat(...), map(...))
  • 这消除了错误,但实际上并没有在显示中连接新流。

标签: angular rxjs


【解决方案1】:

您这样做的问题是订阅将在第一次调用getMediaListBuilderData 后完成。您需要在第一次订阅之前设置 observable 以及它如何连接来自多个来源的结果。此外,如果您希望管道中的操作与每个结果一起发生,则它需要放在流的串联之后。

concat 创建一个 observable,您将在其中传递您的初始调用和一个 Subject,该 Subject 将传递给 increment() 中所有 getMediaListBuilderData 调用的订阅方法。

this.incrementsSubject = new Subject<myType>();
this.contactsDataSource$ = 
    concat(
        this.medialistsrv.getMediaListBuilderData({
            mediaListId: this.mediaListId,
           sortType: this.sortType,
           startRow: this.startRow,
           numRows: this.numRows
        }
        , this.incrementsSubject)
    .pipe(
        tap(response => {
            this.mediaList = response
               .filter(items => items.inMediaList === true)
               .map(items => items.contactId);
            this.mediaList.forEach(id => this._contacts.push(this.fb.control(id)));
        }),
    );

increment() {

    this.medialistsrv
        .getMediaListBuilderData({
            mediaListId: this.mediaListId,
            sortType: this.sortType,
            startRow: (this.numRows + 1),
           numRows: (this.numRows * 2)
         })
         .subscribe(this.incrementsSubject);
}

【讨论】:

  • 目前 contactsDataSource$ 是 contactsDataSource$: Observable&lt;any&gt;; 所以当我实现你上面的内容时,我得到 Type 'UnaryFunction&lt;Observable&lt;{}&gt;, Observable&lt;{}&gt;&gt;' is not assignable to type 'Observable&lt;any&gt;'.
  • 将导入更改为:import { concat } from 'rxjs/observable/concat';
  • 是的,您在这里是正确的。我最终要做的是创建一种包装器 Observable 并将我的所有其他流通过管道/合并到其中。因为每个流都返回一个变异的联系人数组,所以它有效地抵消了最后一个。这有意义吗?
  • 我不太明白发生了什么。当我开始时,我曾经做 wrapper observables,但 Subject 是一个 observable 和 observable 的包装器,应该不需要 Observable 包装器。无论哪种方式都很乐意提供帮助。
猜你喜欢
  • 1970-01-01
  • 2017-03-08
  • 2022-01-02
  • 2021-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
相关资源
最近更新 更多