删除可观察到的操作是取消订阅
Remove observable action is subscription is unsubscribed
我有一个我认为可以通过订阅解决的问题:
refresh$: Subscription;
data$: Subscription;
ngOnInit() {
this.refresh = interval(1000).subscribe(() => {
this.getData();
}
);
}
ngOnDestroy() {
this.refresh$.unsubscribe();
this.data$.unsubscribe();
}
getData() {
this.data$ = service.getData().subscribe(response => {
// here, based on response, I update the header component value whithin an event
}, err => {
// also, if catch error, update header component
});
}
因为我有一个 1 秒的间隔并且服务器已关闭(故意),我的间隔将在 5 秒内发出 5 个请求,但是 foreach 的响应将在 1 秒的时间内到达。
所以,当我发出第一个请求并等待它的回答(这会抛出一个错误)时,已经会发出第二个请求,第三个,等等。
此时,如果我离开页面(调用 ngOnDestroy
),我想从另一个组件更新页眉。但是,离开页面后,我将收到前一个组件的所有响应(成功或失败)。我想在离开时取消所有这些。我以为 unsubscribing
到 data$
会解决这个问题,但问题仍然存在。
谢谢
我找到了一个快速的解决方案,但不是最好的,因为这不会关闭订阅。
声明一个布尔值 pageLeaved = false
并在 ngOnDestroy
上将其设置为真。然后,在订阅错误的情况下,如果 pageLeaved
为真,则只需 return。
pageLeaved = false;
refresh$: Subscription;
data$: Subscription;
ngOnInit() {
this.refresh = interval(1000).subscribe(
() => {
this.getData();
}
);
}
ngOnDestroy() {
this.pageLeaved = true;
this.refresh$.unsubscribe();
this.data$.unsubscribe();
}
getData() {
this.data$ = service.getData().subscribe(response => {
// here, based on response, I update the header component value whithin an event
}, err => {
// also, if catch error, update header component
if (this.pageLeaved) {
return;
}
});
}
请注意,这只是“暂时的解决方案”,因为即使取消订阅可观察对象,也会调用错误案例。如果你有更好的例子,欢迎回答。
您有嵌套订阅,这是一种不好的做法,并且会增加取消订阅所有内部订阅的难度。使用 mergeMap
、switchMap
、concatMap
或 exhaustMap
等可观察映射运算符映射到内部可观察对象,并使用 takeUntil
取消订阅。
private destroy$ = new Subject();
ngOnInit() {
interval(1000).pipe(
concatMap(() => this.getData()),
takeUntil(this.destroy$)
).subscribe(response => {
// update the header component value based on response
});
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
getData(): Observable<any> {
return service.getData().pipe(
catchError(error => {
// update header component on error
return EMPTY; // if the subscribe callback shouldn't be executed on errors
// OR return an observable with the value the subscribe callback in ngOnInit should receive
return of(/* what the header should be set to on errors */)
})
);
}
您也可以使用 async
管道来订阅和处理订阅。也许使用 timer
而不是 interval
来发送第一个请求而没有初始延迟。
data$ = timer(0, 1000).pipe(
concatMap(() => this.getData()),
);
getData(): Observable<any> {
return service.getData().pipe(
catchError(error => {
return of(/* what the header should be set to on errors */)
})
);
}
<header>
<ng-container *ngIf="data$ | async as data">
{{ data }}
</ng-container>
</header>
我有一个我认为可以通过订阅解决的问题:
refresh$: Subscription;
data$: Subscription;
ngOnInit() {
this.refresh = interval(1000).subscribe(() => {
this.getData();
}
);
}
ngOnDestroy() {
this.refresh$.unsubscribe();
this.data$.unsubscribe();
}
getData() {
this.data$ = service.getData().subscribe(response => {
// here, based on response, I update the header component value whithin an event
}, err => {
// also, if catch error, update header component
});
}
因为我有一个 1 秒的间隔并且服务器已关闭(故意),我的间隔将在 5 秒内发出 5 个请求,但是 foreach 的响应将在 1 秒的时间内到达。
所以,当我发出第一个请求并等待它的回答(这会抛出一个错误)时,已经会发出第二个请求,第三个,等等。
此时,如果我离开页面(调用 ngOnDestroy
),我想从另一个组件更新页眉。但是,离开页面后,我将收到前一个组件的所有响应(成功或失败)。我想在离开时取消所有这些。我以为 unsubscribing
到 data$
会解决这个问题,但问题仍然存在。
谢谢
我找到了一个快速的解决方案,但不是最好的,因为这不会关闭订阅。
声明一个布尔值 pageLeaved = false
并在 ngOnDestroy
上将其设置为真。然后,在订阅错误的情况下,如果 pageLeaved
为真,则只需 return。
pageLeaved = false;
refresh$: Subscription;
data$: Subscription;
ngOnInit() {
this.refresh = interval(1000).subscribe(
() => {
this.getData();
}
);
}
ngOnDestroy() {
this.pageLeaved = true;
this.refresh$.unsubscribe();
this.data$.unsubscribe();
}
getData() {
this.data$ = service.getData().subscribe(response => {
// here, based on response, I update the header component value whithin an event
}, err => {
// also, if catch error, update header component
if (this.pageLeaved) {
return;
}
});
}
请注意,这只是“暂时的解决方案”,因为即使取消订阅可观察对象,也会调用错误案例。如果你有更好的例子,欢迎回答。
您有嵌套订阅,这是一种不好的做法,并且会增加取消订阅所有内部订阅的难度。使用 mergeMap
、switchMap
、concatMap
或 exhaustMap
等可观察映射运算符映射到内部可观察对象,并使用 takeUntil
取消订阅。
private destroy$ = new Subject();
ngOnInit() {
interval(1000).pipe(
concatMap(() => this.getData()),
takeUntil(this.destroy$)
).subscribe(response => {
// update the header component value based on response
});
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
getData(): Observable<any> {
return service.getData().pipe(
catchError(error => {
// update header component on error
return EMPTY; // if the subscribe callback shouldn't be executed on errors
// OR return an observable with the value the subscribe callback in ngOnInit should receive
return of(/* what the header should be set to on errors */)
})
);
}
您也可以使用 async
管道来订阅和处理订阅。也许使用 timer
而不是 interval
来发送第一个请求而没有初始延迟。
data$ = timer(0, 1000).pipe(
concatMap(() => this.getData()),
);
getData(): Observable<any> {
return service.getData().pipe(
catchError(error => {
return of(/* what the header should be set to on errors */)
})
);
}
<header>
<ng-container *ngIf="data$ | async as data">
{{ data }}
</ng-container>
</header>