我有一个Angular Http get请求,它会根据返回的数据将路由导航到三个路由之一。示例代码如下:
SomeComponent:
constructor(
private someService: SomeService,
private router: Router
) { }
ngOnInit() {
this.someService.getSomeData().subscribe(
() => {
console.log("getSomeData() did not route to a new link! Routing to a 3rd link");
this.router.navigate(['home']);
},
() => {
console.log("Some error occurred.");
});
SomeService:
constructor(
private router: Router,
private someOtherService: SomeOtherService
) { }
getSomeData() {
return this.someOtherService.getSomeOtherData().map(data => {
if (data === 'someValue') {
console.log("The data was 'someValue'");
this.router.navigate(['route1']);
}
else if (data == 'someOtherValue') {
console.log("The data was 'someOtherValue'");
this.router.navigate(['route2']);
}
});
}
SomeOtherService:
constructor(
private http: Http
) { }
getSomeOtherData() {
return this.http.get(this.getDataUrl) {
.map((res: Response) => {
console.log("Sending over the data back to SomeService");
let body = res.json();
return body.data;
})
.catch((err: Response) => {
console.log(err);
return Observable.throw(err);
});
}
}
预期的行为是,在从SomeOtherService接收数据后,路由器将导航到route1
或route2
,具体取决于数据(我认为我在哪里读取会停止Observable流?也许我误读了)。如果数据不匹配,则Observable流继续到SomeComponent,然后导航到home
。
实际行为是路由器最初将路由到route1
或route2
,但由于流继续,路由器最终会路由到home
。
所以我的问题是,如果您订阅了一个rxjs Observable,有没有办法取消/取消订阅Observable中流?我认为导航到另一条路线会取消观察,但这对我来说似乎不起作用。
我尝试在map
方法中取消订阅有趣(坏)的结果。我也试过看其他的Observable方法但是对rxjs不熟悉我不确定哪种方法最合适(我真的只熟悉map
,catch
,{{ 1}},此时mapTo
)。
答案 0 :(得分:2)
预期的行为是,在从SomeOtherService接收数据后,路由器将导航到route1或route2,具体取决于数据(我认为我在哪里读取会停止Observable流?也许我误读了)。如果数据不匹配,则Observable流继续到SomeComponent,然后导航到home。
不完全: - )
导航到另一个视图会完成旧Observables
提供的所有ActivatedRoute
。您创建的Observables
不是从ActivatedRoute
获取的(也不是通过其他方式绑定到ActivatedRoute
),因此将独立于哪条路线处于活动状态。
此外,router.navigate(...)
是一个异步操作,这意味着它只安排导航,但不等待导航完成。也就是说,即使您的Observables
与ActivatedRoute
绑定,它们仍然存在,并且会通知观察员。
您可以使用以下方法解决此问题:
constructor(
private router: Router,
private someOtherService: SomeOtherService
) { }
getSomeData() {
return this.someOtherService.getSomeOtherData().map(data => {
if (data === 'someValue') {
console.log("The data was 'someValue'");
return ['route1'];
}
else if (data == 'someOtherValue') {
console.log("The data was 'someOtherValue'");
return ['route2'];
} else {
return null;
}
});
}
并使用它:
this.someService.getSomeData().subscribe({
next: (route) => {
this.router.navigate(route || ['home']);
},
error: (err) => {
console.log("Some error occurred.", err);
}
});
顺便说一句,为了更好地了解Observable
是什么,您可能需要阅读ReactiveX documentation。
答案 1 :(得分:1)
有多种方法可以取消订阅可观察的
最直接的方法是保留订阅句柄并取消订阅,例如在OnDestroy方法中。
import { Subscription } from 'rxjs/Rx'
...
private sub: Subscription;
constructor(
private someService: SomeService,
private router: Router
) { }
ngOnInit() {
this.sub = this.someService.getSomeData().subscribe(..)
}
ngOnDestroy() {
if (this.sub) this.sub.unsubscribe();
}
另外在map()方法中导航有点奇怪。 map()运算符用于将可观察流转换为另一个流,它不是端点。通常,您会返回someObs.map(s => s.name).subscribe()
之类的内容。如果您只想做某事,可以使用do()
运算符。
但在你的情况下,如果数据===' someValue'您将首先导航到地图运算符中的route1。然后触发订阅回调(next())并且路由器导航到' home'。
要获得您描述的功能,您可以这样做:
SomeComponent:
constructor(
private someService: SomeService,
private router: Router
) { }
ngOnInit() {
this.someService.getSomeData().subscribe({
next: () => {
console.log("getSomeData() did not route to a new link! Routing to a 3rd link");
this.router.navigate(['home']);
},
complete: () => {},
error: (err) => {
console.log("Some error occurred.", err);
}
});
SomeService:
constructor(
private router: Router,
private someOtherService: SomeOtherService
) { }
getSomeData() {
return Observable.create(observer => {
this.someOtherService.getSomeOtherData().first().subscribe(data => {
if (data === 'someValue') {
console.log("The data was 'someValue'");
this.router.navigate(['route1']);
}
else if (data == 'someOtherValue') {
console.log("The data was 'someOtherValue'");
this.router.navigate(['route2']);
} else {
// none of the options above. call next() on the observer so
// it will route to 'home'
observer.next();
}
observer.complete();
});
});
}