【问题标题】:RxJS SwitchMap doesn't complete if results returned are empty如果返回的结果为空,则 RxJS SwitchMap 不会完成
【发布时间】:2018-01-06 06:54:26
【问题描述】:

我有一个显示加载微调器的数据表。但是,当 this.rendering 设置为 true 时,加载程序会显示 - 如果从 this._CollectionDataSet.results 返回的结果是一个空数组,则序列会卡在 switchMap 并且无法完成 - 为什么会这样?

数据源.ts

connect(): Observable<Collection[]> {
    // Listen for any changes in the base data, sorting, filtering, or pagination
    const displayDataChanges = [
        this._CollectionDataSet.dataChange,
        this._sort.sortChange
    ];

    return Observable.merge(...displayDataChanges)
        .startWith(null)
        .switchMap(() => {
            this.rendering = true;
            return this._CollectionDataSet.dataChange;
        })
        .catch(() => {
            return Observable.of(null);
        })
        .map((result) => {
            this.rendering = false;
            return result;
        })
        .map(result => {
            if (!result) { return []; }

            this._recordsTotal = result.length;

            const sortedData = this.sortData(result.slice());

            this.renderedData = sortedData;

            return this.renderedData;
        });
}

数据集.ts

dataChange: BehaviorSubject<Collection[]> = new BehaviorSubject<Collection[]>([]);
get results(): Collection[] { return this.dataChange.value; }

constructor(
    private _collectionService: CollectionService,
    private route: ActivatedRoute,
    private router: Router
) {
    this.route.params.subscribe((param: any) => {
        this._collectionService.view(param.id).subscribe((results) => this.update(results));
    });
}

update(results: Collection[]) {
    results && this.dataChange.next(results);
}

【问题讨论】:

    标签: typescript rxjs observable


    【解决方案1】:

    您没有向我们展示_CollectionDataSet.results 是如何定义的,而是基于您提供的签名

    (): Collection[]
    

    我假设resultsCollection[] 类型。这里的问题是switchMap 必须返回一个Observable。如果您已经拥有要映射到的数据,则不需要 observable,您可以使用 map 代替。

    此外,您应该使用副作用运算符运行副作用(dotap,当使用 pipe 时)。这将您的代码减少到

    .do(() => this.rendering = true)
    .map((): Collection[] => this._CollectionDataSet.results)
    .catch(result => Observable.of(null))
    .do(() => this.rendering = false)
    

    虽然这些副作用可能没什么用。如果results 确实只是一个数组,那么所有这一切都会立即发生,您最好不要为此显示微调器。

    【讨论】:

    • 我试图传入 this._CollectionDataSet.dataChange - 这是一个定期发出的行为主题 - 这仍然不起作用,因为加载程序永远不会显示。令人困惑。
    • 您必须显示更多代码 = 所有代码都需要具有可重现的情况。如果我们不知道哪个变量包含哪种数据,没有人可以帮助您。
    • 鉴于已设置渲染并且微调器未显示,也许这是微调器本身的问题?
    • 如果我输入 if (result.length) this.rendering = false,它会起作用,但是如果没有结果,加载器会永远显示 - 疯了!
    • 你确定 observable 不会很快发射,以至于微调器永远没有机会显示吗?请注意,当前微调器会在内部可观察对象发出后立即停止显示,而不是在完成时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 1970-01-01
    • 2012-08-19
    相关资源
    最近更新 更多