销毁def sb(Voboll1):
...
并取消订阅this.route.params
后,this.sub
会继续记录。这违反了我的直觉,即通过一次订阅,在取消订阅后,一切都应该停止发生。这里发生了什么&处理它的最佳方法是什么?我应该添加一个takeuntil,还是应该使用concatMap以外的东西? (我正在为新照片投票)
"interval run"
编辑:我尝试重写以使其更清洁, 以下concatMap只进行一次调用,我不确定为什么它在第一次调用后停止工作:
constructor(private authService:AuthService,
private route:ActivatedRoute,
private router:Router,
private photosApi:PhotosApi) {
}
ngOnInit() {
this.sub = this.route.params
.switchMap(()=>{
console.log('switchmap Ruun')
return Observable.interval(2000).startWith(0).concatMap(()=>{
console.log('interval run')
return this.photosApi.apiPhotosGet(this.authService.getAuth(), 0, 40)
})
})
.subscribe((data:PagedResultPatientPhotoModel) => {
this.processPhotos(data)
}).add(()=>console.log('unsubscribe happened'))
只要api调用的运行速度超过3000,以及switchMap就可以运行,否则它们会互相取消:
this.intervalSub = Observable.interval(3000).startWith(0).concatMap(()=>{
console.log('getting photos interval', this.route.params)
return this.route.params.switchMap(()=>{
console.log('getting photos')
return this.photosApi.apiPhotosGet(this.authService.getAuth(), 0, 40)
})
}).subscribe((data:PagedResultPatientPhotoModel) => {
this.processPhotos(data)
}).add(()=>console.log('unsubscribe happened'))
我很好奇为什么switchMap(和mergemap)每次都工作但是concatMap只运行一次,看起来像RXJS中的一个bug
我决定使用mergeMap,因为我觉得请求返回的命令不太可能经常出错,如果是这样,它会在几秒钟后自行纠正。
答案 0 :(得分:1)
问题不是switchMap
,其行为方式与您期望的一样。在以下代码段中,当对组合的observable的订阅被取消订阅时,内部interval
observable被取消订阅:
const source = new Rx.Subject();
const subscription = source
.switchMap(() => {
console.log('> switchmap');
return Rx.Observable.interval(500);
})
.subscribe((value) => console.log(value));
source.next(1);
setTimeout(() => source.next(2), 2000);
setTimeout(() => {
console.log('> unsubscribe');
subscription.unsubscribe();
}, 5000);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
您的问题在于调用订阅的add
方法。这会创建附加订阅,并且该订阅已分配给sub
。
您已添加附加订阅的初始订阅未分配给变量,并且永远不会取消订阅。这是看到interval
继续运行的订阅。
以下代码段显示了问题:
const source = new Rx.Subject();
const subscription1 = source
.switchMap(() => {
console.log('> switchmap');
return Rx.Observable.interval(500);
})
.subscribe((value) => console.log(value));
const subscription2 = subscription1.add(() => console.log('> unsubscribed'));
source.next(1);
setTimeout(() => source.next(2), 2000);
setTimeout(() => {
console.log('> unsubscribe 2');
subscription2.unsubscribe();
}, 5000);
setTimeout(() => {
console.log('> unsubscribe 1');
subscription1.unsubscribe();
}, 6000);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
请注意,在unsubscribe
上调用subscription1
也会看到subscription2
取消订阅 - 但反之亦然。