延迟的 Rxjs BehaviorSubject 机制
deferred Rxjs BehaviorSubject mechanism
我有以下需求。
我有一个带有 BehaviorSubject 的 Angular 服务。
一个 http 请求已完成,完成后 BehaviorSubject.next 方法将用该值调用。
此值可以在单个页面的生命周期内更改。
不同的订阅者注册到它并在它发生变化时被调用。
问题是当 http 请求挂起时,BehaviorSubject 已经包含默认值并且订阅者已经立即获得该值。
我想要的是订阅者必须等到 http 请求完成(延迟)并在 http 请求完成并设置值时获取值。
所以我需要的是某种延迟行为主体机制。
我如何使用 rxjs 实现它?
另一个要求是,如果我在一个方法中订阅了 behaviorsubject,我们希望订阅者获得第一个非默认值并且订阅结束。我们不希望重新执行函数中的本地订阅。
对您的行为主题使用过滤器,这样您的订阅者就不会获得第一个默认发出的值:
mySubject$: BehaviorSubject<any> = new BehaviorSubject<any>(null);
httpResponse$: Observable<any> = this.mySubject$.pipe(
filter(response => response)
map(response => {
const modifyResponse = response;
// modify response
return modifyResponse;
}),
take(1)
);
this.httpResponse$.subscribe(response => console.log(response));
this.myHttpCall().subscribe(response => this.mySubject$.next(response));
如果需要,您当然可以将可观察到的 httpResponse$ 包装在一个方法中。
我认为您想推迟发出的默认值这一事实会立即引起您为什么要使用 BehaviorSubject 的疑问。让我们记住:使用 BehaviorSubject(而不是 Subject 或普通 Observable)的主要原因是 立即 向任何订阅者发出一个值。
如果你需要一个 Observable 类型,你需要控制生产者(通过 .next([value]))and/or 你想要开箱即用的多播订阅,那么 Subject 合适。
如果除此之外还有一个额外的要求是订阅者立即需要一个值,那么你需要考虑BehaviorSubject.
如果您没有说您需要更新来自其他 non-http events/sources 的值,那么我会建议使用 shareReplay(1) 模式。尽管如此...
private cookieData$: Subject<RelevantDataType> = new
Subject<RelevantDataType>(null);
// Function for triggering http request to update
// internal Subject.
// Consumers of the Subject can potentially invoke this
// themselves if they receive 'null' or no value on subscribe to subject
public loadCookieData(): Observable<RelevantDataType> {
this.http.get('http://someurl.com/api/endpoint')
.map(mapDataToRelevantDataType());
}
// Function for dealing with updating the service's
// internal cookieData$ Subject from external
// consumer which need to update this value
// via non-http events
public setCookieData(data: any): void {
const newCookieValue = this.mapToRelevantDataType(data); // <-- If necessary
this.cookieData$.next(newCookieValue); // <-- updates val for all subscribers
}
get cookieData(): Observable<RelevantDataType> {
return this.cookieData$.asObservable();
}
解决方案基于OP评论等。
- 处理订阅主题类型。
- 处理无法直接 'next' 新值的外部订阅者
- 处理能够在 Subject 类型上设置新值的外部生产者
- 处理在 http 请求未决时不提供默认值的问题
我有以下需求。
我有一个带有 BehaviorSubject 的 Angular 服务。 一个 http 请求已完成,完成后 BehaviorSubject.next 方法将用该值调用。 此值可以在单个页面的生命周期内更改。
不同的订阅者注册到它并在它发生变化时被调用。
问题是当 http 请求挂起时,BehaviorSubject 已经包含默认值并且订阅者已经立即获得该值。
我想要的是订阅者必须等到 http 请求完成(延迟)并在 http 请求完成并设置值时获取值。 所以我需要的是某种延迟行为主体机制。
我如何使用 rxjs 实现它?
另一个要求是,如果我在一个方法中订阅了 behaviorsubject,我们希望订阅者获得第一个非默认值并且订阅结束。我们不希望重新执行函数中的本地订阅。
对您的行为主题使用过滤器,这样您的订阅者就不会获得第一个默认发出的值:
mySubject$: BehaviorSubject<any> = new BehaviorSubject<any>(null);
httpResponse$: Observable<any> = this.mySubject$.pipe(
filter(response => response)
map(response => {
const modifyResponse = response;
// modify response
return modifyResponse;
}),
take(1)
);
this.httpResponse$.subscribe(response => console.log(response));
this.myHttpCall().subscribe(response => this.mySubject$.next(response));
如果需要,您当然可以将可观察到的 httpResponse$ 包装在一个方法中。
我认为您想推迟发出的默认值这一事实会立即引起您为什么要使用 BehaviorSubject 的疑问。让我们记住:使用 BehaviorSubject(而不是 Subject 或普通 Observable)的主要原因是 立即 向任何订阅者发出一个值。
如果你需要一个 Observable 类型,你需要控制生产者(通过 .next([value]))and/or 你想要开箱即用的多播订阅,那么 Subject 合适。
如果除此之外还有一个额外的要求是订阅者立即需要一个值,那么你需要考虑BehaviorSubject.
如果您没有说您需要更新来自其他 non-http events/sources 的值,那么我会建议使用 shareReplay(1) 模式。尽管如此...
private cookieData$: Subject<RelevantDataType> = new
Subject<RelevantDataType>(null);
// Function for triggering http request to update
// internal Subject.
// Consumers of the Subject can potentially invoke this
// themselves if they receive 'null' or no value on subscribe to subject
public loadCookieData(): Observable<RelevantDataType> {
this.http.get('http://someurl.com/api/endpoint')
.map(mapDataToRelevantDataType());
}
// Function for dealing with updating the service's
// internal cookieData$ Subject from external
// consumer which need to update this value
// via non-http events
public setCookieData(data: any): void {
const newCookieValue = this.mapToRelevantDataType(data); // <-- If necessary
this.cookieData$.next(newCookieValue); // <-- updates val for all subscribers
}
get cookieData(): Observable<RelevantDataType> {
return this.cookieData$.asObservable();
}
解决方案基于OP评论等。 - 处理订阅主题类型。 - 处理无法直接 'next' 新值的外部订阅者 - 处理能够在 Subject 类型上设置新值的外部生产者 - 处理在 http 请求未决时不提供默认值的问题