我有一个rxjs BehaviorSubject
我订阅了使用Angular 2中的async
管道,我有一个catch
来处理它抛出的最终错误。
问题是,每次我收到一个错误它都会启动一个无限循环,因为我的catch返回从BehaviorSubject
派生的Observable,我认为async
管道在我返回{{1}时重新订阅了observable }。
代码看起来大致如下:
ListService - 是catch
,其中包含BehaviorSubject和@Injectable
的属性。
Observable
ListComponent - 是private listSubject: BehaviorSubject<IItem[]>;
public get listObservable() {
return this.listSubject.asObservable()
}
private error(error: IError) {
this.listSubject.error(error);
}
,显示可观察的列表。
@Component
正如你所看到的,我的catch返回当前的observable,因为它必须返回一个observable。所以,当我发送// Template
<items-view [items]="list | async"></items-view>
// Code
public get list() {
return this.listService.listObservable
.catch((error) => {
this.handleError(error);
return this.listService.listObservable;
});
}
时,代码进入一个无限循环,无限期地调用this.listSubject.error(error)
因为,就像我之前说过的那样,我认为catch
会重新抛出错误因为BehaviourSubject
管道在async
返回时重新订阅了observable。
我试图在错误中返回我之前的缓存数组以返回catch
,但是我遇到了一系列新问题,因为认为async不再订阅Observable.of(error.cached)
就像我之前说过的,这是我真实代码的粗略表示,但逻辑基本上就是这样。
我一直在尝试各种不同的方法,但我无法设法让这个无限循环停止。
提前感谢您的帮助。
答案 0 :(得分:3)
在主题上手动调度错误通常是个坏主意,该错误应该只会弹出数据(例如您的BehaviorSubject
)。原因是,当Subject
发生错误时,Subject
基本上死 - &gt;这意味着,不再有新的数据可以被弹出。这是rxjs的核心概念之一。这是一个小例子:
let stream$ = new Rx.BehaviorSubject(1);
stream$.subscribe(x => console.log("Logging: " + x), e => console.error("Error: " + e)); // logs 1, 2, Error: ...
stream$.next(2);
stream$.error(new Error("Some error message."));
stream$.next(3); // this will have no effect, because the stream is "dead"
stream$.subscribe(x => console.log("Logging 2: " + x), e => console.error("Error: " + e)); // this will just log the error
对于你的情况,这意味着你做了一些错误处理,但只是返回&#34;旧的,死的,错误&#34; -Subject-换句话说:沿着流传播错误。 (我并不是假设handleError()
创建了一个新的Subject
,无论如何这都是一种可怕的做法。)
一般来说,这意味着.error
只应用于执行已定义操作且具有已定义数量的结果然后完成或抛出错误的流,但不应用于Subject
s想要在应用程序的整个生命周期内发出数据。
如何在你的情况下解决这个问题:快速和肮脏(真的很脏!!)的方式是使用两个单独的主题,一个用于数据,一个用于错误(用.next
弹出)。
正确修复:将您的体系结构拆分为数据生成流和数据存储部分。
生命周期看起来像这样:
生成流程
订阅流程
完美修复程序将使用即时使用的思维导致商店架构,如ngrx,但在现有项目中实现此功能将带来重大的重构要求。