I'm a newbie of Angular but in my exercise i'm trying to get total of cart stored from my DB. My function in service returns total if user is logged in or not thanks to a session storage item. First part of function runs perfectly but second fails. In subscribe I get correctly qty of data from consle.log but sum returns always 0. Could you help me? Thanks a lot
userId = sessionStorage.getItem("Utente") || '';
items = this.cartService.getRemoteCart(this.userId) || '[]'
cartProducts: Cart[] = []
total : number = 0;
getCount() : number {
if (!sessionStorage.getItem("User")) {
let cartProducts = JSON.parse(localStorage.getItem('cartProducts') || '{}');
if (cartProducts != null) {
for (var item in cartProducts) {
this.total += cartProducts[item]['qty'];
}
}
return this.total;
}
else {
this.items.subscribe(data => {
for (const obj of data) {
console.log(obj.qty)
this.total += obj.qty
}
}
)
console.log(this.total)
return this.total
}
}
I'm a newbie of Angular but in my exercise i'm trying to get total of cart stored from my DB. My function in service returns total if user is logged in or not thanks to a session storage item. First part of function runs perfectly but second fails. In subscribe I get correctly qty of data from consle.log but sum returns always 0. Could you help me? Thanks a lot
userId = sessionStorage.getItem("Utente") || '';
items = this.cartService.getRemoteCart(this.userId) || '[]'
cartProducts: Cart[] = []
total : number = 0;
getCount() : number {
if (!sessionStorage.getItem("User")) {
let cartProducts = JSON.parse(localStorage.getItem('cartProducts') || '{}');
if (cartProducts != null) {
for (var item in cartProducts) {
this.total += cartProducts[item]['qty'];
}
}
return this.total;
}
else {
this.items.subscribe(data => {
for (const obj of data) {
console.log(obj.qty)
this.total += obj.qty
}
}
)
console.log(this.total)
return this.total
}
}
Share
Improve this question
asked Jan 18 at 17:40
alexalex
792 silver badges9 bronze badges
1
|
2 Answers
Reset to default 1The gist of the problem is, the code inside subscribe is asynchronous
and the code outside it is synchronous
, so always the synchronous
code does not wait for the asynchronous
to complete, so we should move the logic that uses this API data inside the subscribe.
Here we create a function. That makes the API call and we use rxjs reduce
operator which is similar to javascript reduce but can access the inner observable data and reduce it. So the main thing to notice is that, we are executing the logic that uses this count inside the subscribe, so that it waits for the API to complete and then access the response.
userId = sessionStorage.getItem('Utente') || '';
items = this.cartService.getRemoteCart(this.userId) || '[]'
cartProducts: any[] = [];
total: number = 0;
userId = sessionStorage.getItem('Utente') || '';
items = of([]); // this.cartService.getRemoteCart(this.userId) || '[]'
cartProducts: any[] = [];
total: number = 0;
//......
//function in service cart.service.ts
getRemoteCart = (userId : string): Observable<Cart[]> => {
return this.httpClient.get<Cart[]>(`http://${this.server}:${this.port}/api/cart/cerca/${userId}`).pipe(
map(response => {
return response;
})
);
}
methodCallingGetCount() {
let count = 0;
if (!sessionStorage.getItem('User')) {
count = this.getCount();
// trigger other logic here!
this.otherLogicCallback(count);
} else {
this.getCountApi().subscribe((count: number) => {
count = count;
// trigger other logic here!
this.otherLogicCallback(count);
});
}
}
otherLogicCallback(count: number) {}
getCountApi() {
return this.items.pipe(
reduce((acc: number, curr: any) => {
acc += curr?.qty || 0;
return acc;
}, 0)
);
}
getCount(): number {
let cartProducts = JSON.parse(localStorage.getItem('cartProducts') || '{}');
if (cartProducts != null) {
for (var item in cartProducts) {
this.total += cartProducts[item]['qty'];
}
}
console.log(this.total);
return this.total;
}
I haven't usex rxjs, so this may not be right, but I'm going to assume that the .subscribe()
function sets a callback for some time in the future, so the console.log(this.total)
runs before it's actually updated from the subscription thing.
Are you sure you want to be subscribing in a callback, and not during the class creation?
subscribe()
is asynchronous and will be triggered sometime in the future. Simple fix is to return the observable from the service and subscribe to it in the component where it's emissions are required. – Barremian Commented Jan 21 at 17:50