Thomas Schneiter
Thomas Schneiter

Reputation: 1153

Why is this change emitted using Rxjs

I'm a little bit confused as why the following snipped works as expected. The idea of this service is to have a list of strings where if you add a string, it is removed 5 seconds later. Rxjs is used here:

@Injectable()
export class ErrorService {

  private errors: Array<string> = [];
  private emitErrorsChanged = new Subject<any>();
  public emitErrorsChanged$ = this.emitErrorsChanged.asObservable();

  constructor() {
    this.emitErrorsChanged$.delay(5000).subscribe(
      () => {
        if (this.errors.length > 0) {
          this.errors.shift();
        }
      }
    );
  }

  public emitErrorChange(error: string) {
    this.errors.push(`${error}`);
    this.emitErrorsChanged.next(this.errors);
  }
}

An error component is subscribed to this service errorService.emitErrorsChanged$.subscribe(...) and shows the strings in a list. Other components/services add strings by this.errorService.emitErrorChange(error.message).

My question is: why are the removed errors (5s) emitted to the error component? The errors are just removed from the list this.errors.shift(); but the change is not emitted by this.emitErrorsChanged.next(this.errors);

Upvotes: 0

Views: 75

Answers (1)

Daniel Kucal
Daniel Kucal

Reputation: 9232

The behavior occurs because you are passing reference to your object (list in this case). The changes made by this.errors.shift(); are not emitted, but I guess you can see current state of this.errors thanks to Angular's change detection. I have prepared a demo (click) so you can see that the object reference is passed in your case - what means that the list in subscription is the exactly same array list. To prevent it you can pass a copy of your list, e.g. using spread operator like in this example:

this.emitErrorsChanged.next([...this.errors]);

Upvotes: 1

Related Questions