在Angular 2中,有一些您不需要取消订阅的可观察对象。例如http requests和activatedRoute.params。
Angular/RxJs When should I unsubscribe from `Subscription`
但是当我使用switchMap时会发生什么情况,例如activatedRoute.params,在switchMap内部,我访问一个返回一个observable的服务,如果以通常的方式订阅则需要取消订阅。
这样的事情:
this.activatedRoute.params
.switchMap((params: Params) => this.userService.getUser(+params['id']))
.subscribe((user: User) => this.user = user);
如果我在没有switchMap且没有activateRoute.params的情况下调用this.userService,我将不得不取消订阅。
// userService.getUser() takes in optional id?: number.
this.subscription = this.userService.getUser().subscribe(
(user: User) => {
this.user = user;
}
);
然后...... ..
this.subscription.unsubscribe();
我的问题是,如果我在其上使用switchMap并调用需要取消订阅的服务,是否需要取消订阅activatedRoute.params?
答案 0 :(得分:9)
如果您订阅的源可观察对象总是完成或错误,则您无需取消订阅。
但是,如果您使用switchMap
从源中编写另一个可观察对象,则是否需要取消订阅取决于switchMap
内返回的可观察对象。如果返回的observable并不总是完成或错误,那么,是的,您需要取消订阅。
如果源错误,将自动取消订阅:
const source = new Rx.Subject();
const composed = source.switchMap(() => Rx.Observable.interval(200));
composed.subscribe(value => console.log(value));
source.next(1);
setTimeout(() => {
console.log("Erroring...");
source.error(new Error("Boom!"));
}, 1000);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@5.4.1/bundles/Rx.min.js"></script>
但是,如果源完成,则不会发生自动取消订阅:
const source = new Rx.Subject();
const composed = source.switchMap(() => Rx.Observable.interval(200));
composed.subscribe(value => console.log(value));
source.next(1);
setTimeout(() => {
console.log("Completing...");
source.complete();
}, 1000);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@5.4.1/bundles/Rx.min.js"></script>
答案 1 :(得分:0)
一旦您进行了切换映射,订阅将附加到最后一个可观察对象。如果第一个可观察对象持续触发,则无关紧要。 switchmap块仅执行一次。
如果永不关闭,则必须从最后一个取消注册。
检查此代码:
import { Component, OnInit } from '@angular/core';
import { Observable, BehaviorSubject, Subscription} from 'rxjs';
import * as Rx from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app works!';
private source: Rx.Subject<any>;
private source2: Rx.Subject<any>;
private composed: Rx.Observable<any>;
private composedSub: Subscription;
public ngOnInit(): void {
this.source = new Rx.Subject();
this.source2 = new Rx.Subject();
this.composed = this.source.switchMap(value => this.source2);
this.composedSub = this.composed.subscribe(value => console.log(value));
console.log(this.composedSub);
}
private onClick() {
// Triggers the first observable, the console.log is never executed.
this.source.next(1);
}
private onClick2() {
// Console.log is executed, prints "1"
this.source2.next(1);
}
private onClick3() {
// The console log is never called again after click on this button.
this.composedSub.unsubscribe();
}
private onClick4() {
// The first observable finish. the console log keeps printing unles onClick3 is executed
this.source.complete();
}
private onClick5() {
// console.log never executed egain.
this.source2.complete();
}
}
答案 2 :(得分:0)
switchMap
在上一个和新的可观察对象之间创建链接。如果更改第一个可观察值,则将始终触发第二个。
在switchMap
之后订阅的所有内容都会听到初始可观察值和返回可观察值的变化。
使用take
,takeUntil
或takeWhile
来完全停止第一个可观察对象以更新第二个或其他对象。喜欢:
const howTimerWorks = interval(5000).pipe(
take(2), // only get 2 responses after 5 seconds each
switchMap(initialNumber => interval(1000)));
// 0 after 5s, then 1, 2 , 3, (new Subs) 0, 1, ... every sec, forever now.
howTimerWorks.subscribe(console.log)