倍增订阅
Multiplied subscription
在一个组件中我有两个订阅,一个用于查询参数,一个用于 http GET 请求。
在此页面上,用户还可以选择在不同类型的数据之间切换(只能显示一种类型)。当用户点击一个选项时,查询参数更新,订阅也更新,所以再次调用http GET请求,数据也更新,如下:
constructor(private service: DataService, private route: ActivatedRoute) {}
ngOnInit() {
this.route.queryParams.subscribe(params => {
this.dataType = params["dataType"];
this.service
.getData(this.dataType)
.subscribe(data => {
this.data=data;
})
})
}
在html中:
[queryParams]="{ dataType: row.dataType}"
问题是,每次用户单击不同类型的数据时,都会从 http GET 请求创建新的订阅,因为一切都发生在同一个组件中。因此,当创建组件时:2 个订阅,
用户点击新数据类型:加载新数据和 3 个订阅,用户点击不同数据类型,加载新数据和 4 个订阅等等。正如您可以想象的那样,点击 4-5 次后页面就会崩溃。
我一直在努力寻找这个问题的解决方案(特别是根据用户的选择在同一组件中加载数据),但我不知道该怎么做。
任何帮助将不胜感激
将您当前的订阅保存在一个变量中,然后在创建新订阅之前将其关闭:
subscription: currSubscribtion;
constructor(private service: DataService, private route: ActivatedRoute) {}
ngOnInit() {
this.route.queryParams.subscribe(params => {
if (currSubscribtion) {
this.currSubscribtion.unsubscribe()
}
this.dataType = params["dataType"];
this.currSubscribtion = this.service.getData(this.dataType)
.subscribe(data => {
this.data=data;
})
})
}
一些 RxJS 管道运算符应该可以解决这个问题:
switchMap
- 将取消之前的 http 请求并切换到最新的
使用 takeUntil
方法取消订阅
tap
副作用(在订阅中不这样做有点难看)
ngOnInit() {
this.route.queryParams.pipe(
map(params => params["dataType"]),
tap(dataType => {
this.dataType = dataType
}),
switchMap(dataType => this.service.getData(this.dataType)),
takeUntil(this.destroyed$)
).subscribe(data => {
this.data = data;
})
}
编辑 - make takeUntil 最后一个运算符!
此代码无法解决您的问题,但您正在使用两个异步事件中的一个。这不是一个好习惯。
您可以用它来更新您的代码:
this.route.queryParams.pipe(
switchMap(params => this.service.getData(params["dataType"]))
).subscribe(data => this.data = data);
为了解决您的订阅问题,您是否尝试添加 ngOnDestroy()
功能?
Http 方法是冷可观察对象,因此您无需取消订阅。它将自动取消订阅。
相反,您应该取消订阅 router.queryParams
订阅,这是一个热观察。此订阅已在您的代码中多次创建。
这可以在 ngOnDestroy
生命周期挂钩
中完成
routerSub: Subscription;
constructor(private service: DataService, private route: ActivatedRoute) {}
ngOnInit() {
this.routerSub = this.route.queryParams.subscribe(params => {
this.dataType = params["dataType"];
this.service
.getData(this.dataType)
.subscribe(data => {
this.data=data;
})
})
}
ngOnDestroy() {
this.routerSub.unsubscribe();
}
在一个组件中我有两个订阅,一个用于查询参数,一个用于 http GET 请求。 在此页面上,用户还可以选择在不同类型的数据之间切换(只能显示一种类型)。当用户点击一个选项时,查询参数更新,订阅也更新,所以再次调用http GET请求,数据也更新,如下:
constructor(private service: DataService, private route: ActivatedRoute) {}
ngOnInit() {
this.route.queryParams.subscribe(params => {
this.dataType = params["dataType"];
this.service
.getData(this.dataType)
.subscribe(data => {
this.data=data;
})
})
}
在html中:
[queryParams]="{ dataType: row.dataType}"
问题是,每次用户单击不同类型的数据时,都会从 http GET 请求创建新的订阅,因为一切都发生在同一个组件中。因此,当创建组件时:2 个订阅, 用户点击新数据类型:加载新数据和 3 个订阅,用户点击不同数据类型,加载新数据和 4 个订阅等等。正如您可以想象的那样,点击 4-5 次后页面就会崩溃。
我一直在努力寻找这个问题的解决方案(特别是根据用户的选择在同一组件中加载数据),但我不知道该怎么做。 任何帮助将不胜感激
将您当前的订阅保存在一个变量中,然后在创建新订阅之前将其关闭:
subscription: currSubscribtion;
constructor(private service: DataService, private route: ActivatedRoute) {}
ngOnInit() {
this.route.queryParams.subscribe(params => {
if (currSubscribtion) {
this.currSubscribtion.unsubscribe()
}
this.dataType = params["dataType"];
this.currSubscribtion = this.service.getData(this.dataType)
.subscribe(data => {
this.data=data;
})
})
}
一些 RxJS 管道运算符应该可以解决这个问题:
switchMap
- 将取消之前的 http 请求并切换到最新的
使用 takeUntil
方法取消订阅
tap
副作用(在订阅中不这样做有点难看)
ngOnInit() {
this.route.queryParams.pipe(
map(params => params["dataType"]),
tap(dataType => {
this.dataType = dataType
}),
switchMap(dataType => this.service.getData(this.dataType)),
takeUntil(this.destroyed$)
).subscribe(data => {
this.data = data;
})
}
编辑 - make takeUntil 最后一个运算符!
此代码无法解决您的问题,但您正在使用两个异步事件中的一个。这不是一个好习惯。
您可以用它来更新您的代码:
this.route.queryParams.pipe(
switchMap(params => this.service.getData(params["dataType"]))
).subscribe(data => this.data = data);
为了解决您的订阅问题,您是否尝试添加 ngOnDestroy()
功能?
Http 方法是冷可观察对象,因此您无需取消订阅。它将自动取消订阅。
相反,您应该取消订阅 router.queryParams
订阅,这是一个热观察。此订阅已在您的代码中多次创建。
这可以在 ngOnDestroy
生命周期挂钩
routerSub: Subscription;
constructor(private service: DataService, private route: ActivatedRoute) {}
ngOnInit() {
this.routerSub = this.route.queryParams.subscribe(params => {
this.dataType = params["dataType"];
this.service
.getData(this.dataType)
.subscribe(data => {
this.data=data;
})
})
}
ngOnDestroy() {
this.routerSub.unsubscribe();
}