Angular:是否应该取消订阅由 shareReplay(1) 传输的 forkJoin?
Angular : Should unsubscribe from forkJoin piped by shareReplay(1)?
我想知道是否有必要取消订阅 来自 forkJoin([..])
使用一组由 shareReplay(..)
操作员传输的 HttpClient Observables 制作的 Observables?
我读到 forkJoin(..)
它会自动取消订阅,但我不知道在使用 shareReplay(..)
运算符进行管道传输时是否也是这种情况,因为我读到这个可以导致 内存泄漏如果使用不当会出现问题。
我的以下示例用于缓存 Http 请求结果,这是我的代码块:
服务:
@Injectable()
export class HttpcatcherService {
codeNafsObservable$: Observable<any>;
constructor(private positionservice: PositionserviceService) {}
getAllEntities(refresh?: boolean): Observable<any> {
if (!this.codeNafsObservable$ || refresh) {
this.codeNafsObservable$ = forkJoin([
this.positionservice.getPosts(), // returns Observable
this.positionservice.getComments(), // returns Observable
]).pipe(
map((result) => {
return {
secondNaf: result[0],
thirdNaf: result[1],
};
}),
shareReplay(1)
);
}
return this.codeNafsObservable$;
}
}
我的组件(知道我在不同的组件中也使用相同的 way/logic):
@Component({
selector: 'hello',
templateUrl: './hello.component.html',
styles: [`h1 { font-family: Lato; }`],
})
export class HelloComponent implements OnInit {
constructor(private httpCat: HttpcatcherService) {}
ngOnInit(): void {
this.httpCat
.getAllEntities()
.subscribe(
(result) => {
console.log(result);
});
}
}
我认为 forkJoin
与 shareReplay
一起使用不会导致任何内存泄漏问题。原因如下:
forkJoin
当所有 Observables 作为参数传入时通知 complete
。在这种情况下,由于传递给 forkJoin
的 Observable 与 http 调用有关,因此它们会在 http 调用 return 之后完成。因此,只要两个 http 调用 return,forkJoin
创建的 Observable 就会通知并完成。
shareReplay
的作用是创建一个内部缓存,确保任何订阅都将获得上游通知的最后一个值。在这种情况下,upstream 通知的最后一个值是 forkJoin
创建的 Observable 通知的唯一值
当源 Observable 是无限流时(例如使用 interval
创建的流),内存泄漏的风险或者至少是使用 shareRepley
不受控制地执行代码的风险.在这种情况下,shareReplay
创建一个永远不会完成的 Observable,即使没有订阅者,除非 ShareReplayConfig
的 refCount
属性 设置为 true
。
详细解释了此行为 in the documentation。
在任何情况下,这都不是您的风险 运行,因为您拥有的源 Observable 只会发出一次然后完成。
从 RxJS 7 开始,shareReplay(1)
是一个包含以下参数的 share 包装器:
share({
connector: () => new ReplaySubject(1),
resetOnComplete: false,
resetOnError: false,
resetOnRefCountZero: false
})
如果您想更好地控制 shareReplay
的工作方式,请改用 share
并根据需要设置配置选项。
例如,如果您将 resetOnRefCountZero
设置为 true,那么当不再有任何订阅者时,内部 ReplaySubject 将被取消订阅。
我想知道是否有必要取消订阅 来自 forkJoin([..])
使用一组由 shareReplay(..)
操作员传输的 HttpClient Observables 制作的 Observables?
我读到 forkJoin(..)
它会自动取消订阅,但我不知道在使用 shareReplay(..)
运算符进行管道传输时是否也是这种情况,因为我读到这个可以导致 内存泄漏如果使用不当会出现问题。
我的以下示例用于缓存 Http 请求结果,这是我的代码块:
服务:
@Injectable()
export class HttpcatcherService {
codeNafsObservable$: Observable<any>;
constructor(private positionservice: PositionserviceService) {}
getAllEntities(refresh?: boolean): Observable<any> {
if (!this.codeNafsObservable$ || refresh) {
this.codeNafsObservable$ = forkJoin([
this.positionservice.getPosts(), // returns Observable
this.positionservice.getComments(), // returns Observable
]).pipe(
map((result) => {
return {
secondNaf: result[0],
thirdNaf: result[1],
};
}),
shareReplay(1)
);
}
return this.codeNafsObservable$;
}
}
我的组件(知道我在不同的组件中也使用相同的 way/logic):
@Component({
selector: 'hello',
templateUrl: './hello.component.html',
styles: [`h1 { font-family: Lato; }`],
})
export class HelloComponent implements OnInit {
constructor(private httpCat: HttpcatcherService) {}
ngOnInit(): void {
this.httpCat
.getAllEntities()
.subscribe(
(result) => {
console.log(result);
});
}
}
我认为 forkJoin
与 shareReplay
一起使用不会导致任何内存泄漏问题。原因如下:
forkJoin
当所有 Observables 作为参数传入时通知complete
。在这种情况下,由于传递给forkJoin
的 Observable 与 http 调用有关,因此它们会在 http 调用 return 之后完成。因此,只要两个 http 调用 return,forkJoin
创建的 Observable 就会通知并完成。shareReplay
的作用是创建一个内部缓存,确保任何订阅都将获得上游通知的最后一个值。在这种情况下,upstream 通知的最后一个值是forkJoin
创建的 Observable 通知的唯一值
当源 Observable 是无限流时(例如使用 interval
创建的流),内存泄漏的风险或者至少是使用 shareRepley
不受控制地执行代码的风险.在这种情况下,shareReplay
创建一个永远不会完成的 Observable,即使没有订阅者,除非 ShareReplayConfig
的 refCount
属性 设置为 true
。
详细解释了此行为 in the documentation。
在任何情况下,这都不是您的风险 运行,因为您拥有的源 Observable 只会发出一次然后完成。
从 RxJS 7 开始,shareReplay(1)
是一个包含以下参数的 share 包装器:
share({
connector: () => new ReplaySubject(1),
resetOnComplete: false,
resetOnError: false,
resetOnRefCountZero: false
})
如果您想更好地控制 shareReplay
的工作方式,请改用 share
并根据需要设置配置选项。
例如,如果您将 resetOnRefCountZero
设置为 true,那么当不再有任何订阅者时,内部 ReplaySubject 将被取消订阅。