Reputation: 53
I have service in Angular where I am trying to create a addCart function that adds the argument menuItem to the behaviorSubject serviceCart that contains an array of values. Then, getCart is called which console logs whatever is in serviceCart.
Here is the code:
private serviceCart = new BehaviorSubject([]);
initializeCart() {
this.serviceCart.next([]);
}
getCart() {
this.serviceCart.subscribe(result => console.log('SERVICECART:', result));
}
addCart(menuItem) {
this.serviceCart.subscribe(result => {
result.push(menuItem);
this.serviceCart.next(result);
this.getCart();
});
}
I want the addCart function to only console log one instance of the array. However, whenever I call addCart, it returns a thousands of instances of the serviceCart array and the error:
ERROR RangeError: Maximum call stack size exceeded
at SafeSubscriber.__tryOrUnsub (Subscriber.js:191)
at SafeSubscriber.next (Subscriber.js:122)
at Subscriber._next (Subscriber.js:72)
at Subscriber.next (Subscriber.js:49)
at BehaviorSubject.next (Subject.js:39)
at BehaviorSubject.next (BehaviorSubject.js:30)
at SafeSubscriber._next (cart.service.ts:28)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
at SafeSubscriber.next (Subscriber.js:122)
at Subscriber._next (Subscriber.js:72)
I am pretty new to RxJs so any help would be appreciated!
Upvotes: 0
Views: 1972
Reputation: 21638
You should not be subscribing to observables in your service, it should be the consumers of your service that subscribe, ie the components. You should not be mutating objects stored in the behavior subject with push, you should create a new array with the spread operator. You should use the standard naming convention of ending observables with a $.
serviceCart$ = new BehaviorSubject([]);
addCart(menuItem) {
this.serviceCart$.next([...this.serviceCart$.value, menuItem]);
}
and in your component you should add the observable as a property to the component
serviceCart$ = this.cartService.serviceCart$;
and in your template you subscribe with the async pipe
<ng-container *ngIf="serviceCart$ | async as serviceCart">
// use the view variable serviceCart here which will automagically update
</ng-container>
Upvotes: 2
Reputation: 18805
You have an infinite loop
this.serviceCart.subscribe(result => { // do on serviceCart change
result.push(menuItem);
this.serviceCart.next(result); // change serviceCart
this.getCart();
});
You might want to unsubscribe:
var sub = this.serviceCart.subscribe(result => { // do on serviceCart change
result.push(menuItem);
sub.unsubscribe();
this.serviceCart.next(result); // change serviceCart
this.getCart();
});
Upvotes: 1