【问题标题】:Adding to previous result, Observable pipeline only running once添加到之前的结果,Observable 管道只运行一次
【发布时间】:2018-06-23 14:45:18
【问题描述】:

live example

我有一个过滤器数组作为Observable,我想从中添加/删除过滤器。这是我目前仅在函数第一次运行时添加Filter 的代码。

第二次什么都没发生。

private _filters$ = new BehaviorSubject<Filter[]>([]);

addFilter(added: Filter) {
    debugger
    // adding to array of filters
    this._filters$.pipe(
        tap(d => { debugger; }),
        first(), 
        map(filters => ([...filters, added]))
    ).subscribe(this._filters$);
}

所以我的问题是:为什么会发生这种情况?为什么它只运行一次? (顺便说一下first() 不是原因)。

我知道我可以让代码像这样工作:

private _filters$ = new BehaviorSubject<Filter[]>([]);

currentFilters;

init() {
   this._filters$.subscribe(f => this.currentFilters = f);
}

addFilter(added: Filter) {
    this._filters$.next([...this.currentFilters, added]);
}

【问题讨论】:

    标签: rxjs rxjs5 rxjs6


    【解决方案1】:

    其实是因为first。当您第一次运行该函数时,它会创建流并订阅BehaviorSubject。当它接收到第一个事件时,它会将其转发给BehaviorSubject,然后完成BehaviorSubject。第二次运行它BehaviorSubject 已经关闭,所以它会立即取消订阅它的任何新订阅。

    在不太了解您的实际目标的情况下,我的建议是不要将 BehaviorSubject 放在管道的底部,而是将其放在顶部。

    // You don't actually need the caching behavior yet so just use a `Subject`
    private _filters$ = new Subject<Filter>()
    
    // Hook this up to whatever is going to be using these filters
    private _pipeline$ = this._filters.pipe(
      // Use scan instead mapping back into self
      scan((filters, newFilter) => ([...filters, newFilter]), []),
      // Store the latest value for new subscribers
      shareReplay(1)
    );
    
    // Now this method is just pushing into the `Subject` and the pipeline never has to be torn down
    addFilter(added: Filter) {
        debugger
        this._filters$.next(added);
    }
    

    【讨论】:

    • 我应该仔细检查first,我可能有另一个在我的真实代码中阻止了它。关于您的回答,我看到一个问题和一个问题。问题是 _pipeline$ 是我们订阅的内容,但它假设我们只是添加过滤器。而在我的情况下,我确实删除/添加。问题是您是否使用shareReplay(1) 而不是在顶部使用BehaviorSubject 以避免订阅时的额外计算?
    • 对于您提到的问题,我建议您查看另一个具有类似问题的 SO question(处理数字而不是数组,但原理相同)stackoverflow.com/questions/31434606/…。我将逻辑切换为使用shareReplay,因为它更具语义且不易出错。使用原始主题进行状态管理通常被认为是一种反模式,因为通常情况下,您最终会发现泄漏状态。运营商倾向于管理自己的生命周期。
    • 好的,谢谢,我的用例看起来很复杂,所以我最终在我的问题中使用了我在 sn-p 中的内容。关于使用它的任何反指示?
    猜你喜欢
    • 2020-01-04
    • 2020-10-21
    • 2019-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 2020-07-12
    相关资源
    最近更新 更多