![](/img/trans.png)
[英]Angular RXJS Observables - ObjectUnsubscribedError
[英]Angular/RxJs - Calling next() on Observable in service after component was unsubscribe() cause ObjectUnsubscribedError
我有一個定義公共
Subject<\/code>的 Angular 服務。
稍后在某些情況下,服務將在此主題上調用
.next()<\/code> 。
此外,我有一個 Angular 組件,它在它的 ngOnInit() 方法中
.subscribe()<\/code>到這個 Subject,並在它的
ngOnInit()<\/code>方法中調用
.unsubscribe()<\/code>
ngOnDestroy()<\/code>
雖然服務和組件都還活着,但我的代碼工作正常。 但是,用戶可以在我的應用程序中單擊不同的選項卡。 這導致我的組件卸載並調用其
ngOnDestroy()<\/code>方法,這意味着 Observable 已取消訂閱。
從這一點開始,組件不再存在,但服務仍然存在 - 其他組件仍在使用它。
當服務在組件調用
.unsubscribe()<\/code>之后調用
.next()<\/code>方法時,會拋出此錯誤ObjectUnsubscribedError<\/em> 。
ERROR Error: Uncaught (in promise): ObjectUnsubscribedError: object unsubscribed<\/code>
此外,稍后如果用戶返回到包含該組件的選項卡,則會執行
ngOnInit()<\/code>並且重新訂閱此 observable 會再次引發相同的錯誤。
我做錯了什么,我該如何解決這些錯誤?
import { Subject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class StatusService {
public statusChange$: Subject<number>;
public constructor(...) {
this.statusChange$ = new Subject<number>();
}
public someInternalLogic(someNumber: number): void {
this.statusChange$.next(someNumber);
// this will throw an error if StatusComponent call .unsubscribe()
}
}
@Component({
selector: 'app-status',
templateUrl: './status.component.html',
styleUrls: ['./status.component.scss']
})
export class StatusComponent implements OnInit, OnDestroy {
public constructor(
private _statusService: StatusService) {}
public ngOnInit(): void {
this._statusService.statusChange$.subscribe(value => this._onStatusChange(value));
}
public ngOnDestroy(): void {
this._statusService.statusChange$.unsubscribe();
// after this point if the StatusService calling .next() an error will be thrown
}
private _onStatusChange(value: number): void {
// ....
}
}
您不需要在組件中取消訂閱服務主題。 而是在組件中為服務主題創建訂閱變量,並在組件銷毀時取消訂閱
subscription!: Subscription;
public ngOnInit(): void {
this.subscription = this._statusService.statusChange$.subscribe(value => this._onStatusChange(value));
}
public ngOnDestroy(): void {
this.subscription.unsubscribe();
}
private _onStatusChange(value: number): void {
// ....
}
另一種集體取消訂閱 OnDestroy 事件的方法是使用 takeUntil 運算符。 因此,您不必存儲每個訂閱,而是可以創建一個主題並在組件被銷毀時觸發它。
想象一下,您的服務有多個主題,並且您的組件訂閱了每個主題。 在這種情況下,您必須通過類屬性(或一系列訂閱)存儲您的所有訂閱,並且您必須手動取消訂閱每個訂閱。
class myComponent {
// create any subject which allows you to push into
// when your component gets destroyed
private onDestroy = new Subject<void>();
public ngOnInit(): void {
// Subscription #1
this._statusService.statusChange_1$.pipe(
tap(() => /* do something */),
// takeUntil will listen to changes of the onDestroy subject
// and whenever you trigger it by this.onDestroy.next() it will
// automatically unsubsribe for you
takeUntil(this.onDestroy)
).subscribe();
// Subscription #2
this._statusService.statusChange_2$.pipe(
takeUntil(this.onDestroy)
).subscribe(value => {
/* do something else */
// you can put your logic into your subscribe method as well
// like you did in your question
});
// Any number of more subscriptions...
// ...
}
public ngOndestroy(): void {
// Notify the observers to unsibscribe
this.onDestroy.next();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.