ngneat / until-destroy

🦊 RxJS operator that unsubscribe from observables on destroy

Home Page:https://netbasal.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ObjectUnsubscribedError in Angular 11

ArkasDev opened this issue · comments

I use @UntilDestroy({ checkProperties: true }) with check properties to unsubscribe all observables in my components. The following error occurs very often. Unfortunately, I do not understand the error message and there is no good logging trace. Am I using until-destroy incorrectly? Why does the error occur?

core.js:5980 ERROR
ObjectUnsubscribedErrorImpl {message: "object unsubscribed", name: "ObjectUnsubscribedError"}
message: "object unsubscribed"
name: "ObjectUnsubscribedError"

"@ngneat/until-destroy": "^8.1.3",
"@angular/core": "^11.0.0",
commented

The error occurs if you try to do anything with a closed observable, e.g. call next() or subscribe().

I have been trying to find the piece of code that is causing this error. I don't unsubscribe manually in this code, do you know why this error occurs in this component?

@UntilDestroy({ checkProperties: true })
@Component({
  selector: 'device-view-driver',
  template: `
    <web-ide
      [device$]="device$"
      [deviceState$]="deviceState$"
      [deviceTemplate$]="deviceTemplate$"
      [deviceConfig$]="deviceConfig$"
    ></web-ide>
  `,
  styleUrls: ['./device-view-driver.component.scss'],
})
export class DeviceViewDriverComponent implements OnInit {
  public deviceId: string;

  public device$: ReplaySubject<Device> = new ReplaySubject<Device>(1);
  public deviceTemplate$: ReplaySubject<DeviceTemplate> = new ReplaySubject<DeviceTemplate>(1);
  public deviceState$: ReplaySubject<DeviceState> = new ReplaySubject<DeviceState>(1);
  public deviceConfig$ = new ReplaySubject<DeviceConfig>(1);

  constructor(private route: ActivatedRoute, private store: Store) {}

  public ngOnInit(): void {
    this.onLoadUrlParam();
    this.onLoadDevice();
    this.onLoadDeviceState();
    this.onLoadDeviceTemplate();
    this.onLoadDeviceConfig();
  }

  private onLoadDevice(): void {
    this.store.select(DeviceStore.getDevice(this.deviceId)).subscribe((device) => {
      this.device$.next(device);
    });
  }

  private onLoadDeviceState(): void {
    this.store.select(DeviceStateStore.getDeviceState(this.deviceId)).subscribe((deviceState) => {
      this.deviceState$.next(deviceState);
    });
  }

  private onLoadDeviceTemplate(): void {
    this.store.select(DeviceTemplateStore.getDeviceTemplateByDeviceId(this.deviceId)).subscribe((deviceTemplate) => {
      this.deviceTemplate$.next(deviceTemplate);
    });
  }

  private onLoadDeviceConfig(): void {
    this.store.select(DeviceConfigStore.getdeviceConfigOfDevice(this.deviceId)).subscribe((config) => {
      this.deviceConfig$.next(config);
    });
  }

  private onLoadUrlParam(): void {
    this.route.parent.params.subscribe((param) => {
      this.deviceId = param.deviceId;
    });
  }
}

commented

Well, errors have stack traces logged to the console. You can go through the stack trace and see the place where the error is thrown.

You don't unsubscribe from store.select() and it seems like those streams keep emitting values after the component got destroyed. You have replay subjects and UntilDestroy invokes unsubscribe() on them:

const { ReplaySubject } = require('rxjs');

const device$ = new ReplaySubject(1);
device$.unsubscribe();

device$.next(); // Error here

The error should be stopped being thrown if you unsubscribe from store.select by piping them through the untilDestroyed(this).

commented

I've published 8.1.4 which doesn't touch anything except Subscription instance.