RXJS可观察取消订阅内部可观察量

时间:2017-07-12 22:51:22

标签: angular rxjs observable

销毁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,因为我觉得请求返回的命令不太可能经常出错,如果是这样,它会在几秒钟后自行纠正。

1 个答案:

答案 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取消订阅 - 但反之亦然。