最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

rxjs - Angularjs - get sum through loop in subscribers - Stack Overflow

programmeradmin2浏览0评论

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
  • Long story short. The 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
Add a comment  | 

2 Answers 2

Reset to default 1

The 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?

发布评论

评论列表(0)

  1. 暂无评论