Множественная подписка angular 6

Я создаю интернет-магазин с некоторыми товарами. Пользователь может добавить в корзину и видеть добавленные им продукты. У меня три категории. Одна категория - это все продукты, в которых я отображаю все продукты и одну категорию фруктов и хлеба, где я показываю определенные продукты .. Все работает нормально, но когда я меняю категорию, не нажимая кнопку добавления в корзину, angular выполняет метод addToCart .. Я думаю, что это проблема с множественными подписками и утечкой памяти .. Как я могу сделать это с лучшим кодированием? Вот мои угловые файлы ts и html.

Мои продукты.

import {Component, OnDestroy, OnInit} from '@angular/core';
import {CategoryService} from '../category.service';
import {ActivatedRoute} from '@angular/router';
import {Subject} from 'rxjs/index';
import 'rxjs/add/operator/takeUntil';
import {ShoppingCartService} from '../services/shopping-cart.service';
import {Product} from '../models/product';




@Component({
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.css'],

})
export class ProductsComponent implements OnInit, OnDestroy {

  products: any;
  filteredproducts: any;
  category: any;
  res: any;
  categoryid: any;
  cartId: any;
  private ngUnsubscribe: Subject<any> = new Subject();





  constructor(private service: CategoryService,
              private route: ActivatedRoute,
              private cartService: ShoppingCartService) {


  }


ngOnInit() {

  this.route.queryParamMap.takeUntil(this.ngUnsubscribe).subscribe(params => {
    this.category = params.get('category');
    this.cartId = localStorage.getItem('cartId');
    if (this.category) {
        setTimeout(() => {
            this.service.allProductNames(this.category, this.cartId).takeUntil(this.ngUnsubscribe).subscribe(data => {
                this.filteredproducts = this.products = data;
            });
        }, 500);

    } else {
        if (this.cartId === null) {this.cartId = -1; }
        setTimeout(() => {
            this.service.getProducts(this.cartId).takeUntil(this.ngUnsubscribe).subscribe(data => {
                this.filteredproducts = data;
            });
        }, 500);


    }

  });


}


    addToCart(products: Product) {

        const cartId = this.cartService.getOrCreateCartId();

        if (!cartId) {
         const imero = new Date().getTime();
         this.cartService.create(imero).takeUntil(this.ngUnsubscribe).subscribe(res => {
           this.res = res;
           localStorage.setItem('cartId', this.res.id);
           this.route.queryParamMap.takeUntil(this.ngUnsubscribe).subscribe(params => {
           this.categoryid = params.get('category');
           if (this.categoryid) {
            this.cartService.createItem(products.id, this.res.id).
            takeUntil(this.ngUnsubscribe).subscribe(res1 => {
                setTimeout(() => {
                    this.service.allProductNames(this.category, this.res.id).takeUntil(this.ngUnsubscribe).subscribe(data => {
                        this.filteredproducts = this.products = data;});
                }, 500);

            });

           } else {
           this.cartService.createItem(products.id, this.res.id).takeUntil(this.ngUnsubscribe).subscribe(res2 => {
               setTimeout(() => {
                   this.service.getProducts(this.res.id).takeUntil(this.ngUnsubscribe).subscribe(data => {
                       this.filteredproducts = data;
                   });
               }, 500);

           } );
              }

                });
            });

        }


        else {
            this.route.queryParamMap.takeUntil(this.ngUnsubscribe).subscribe(params => {
                this.categoryid = params.get('category');
                this.cartId = localStorage.getItem('cartId');
                if (this.category) {
                    this.cartService.createItem(products.id, this.cartId).takeUntil(this.ngUnsubscribe).subscribe(res1 => {});
                    setTimeout(() => {
                        this.service.allProductNames(this.category, this.cartId).takeUntil(this.ngUnsubscribe).subscribe(data => {
                            this.filteredproducts = data;
                            });

                    }, 500);

                } else {
                    this.cartService.createItem(products.id, this.cartId).takeUntil(this.ngUnsubscribe).subscribe(res1 => {});
                    setTimeout(() => {
                        this.service.getProducts(this.cartId).takeUntil(this.ngUnsubscribe).subscribe(data => {
                            this.filteredproducts = data;
                            console.info(this.products);});

                    }, 500);
                }





            });

        }
    }



ngOnDestroy() {
  this.ngUnsubscribe.next();
  this.ngUnsubscribe.complete();
}

}

Мои продукты.html

<div class = "row">
  <div class = "col-sm-3">
<app-product-filter></app-product-filter>
  </div>
  <div class = "col-sm-9">
    <div class = "row">
      <ng-container  *ngFor = "let p of filteredproducts; let i = index">
        <div class = "col">
            <div class = "card">
                <img  class = "card-img-top" src = "{{p?.imageUrl}}" style = "max-height: 200px; width: 100%;">
                <div class = "card-body">
                    <h5 class = "card-title">{{p?.title}}</h5>
                    <p class = "card-text">{{p?.price | currency: 'EUR': symbol }}</p>
                </div>
                <div class = "card-footer">
                    <button (click) = "addToCart(p)" class = "btn btn-primary btn-block">Add to Cart</button>
                    <div *ngIf = "p?.quantity!=0">{{p?.quantity}}</div>
                </div>
            </div>

        </div>
        <div *ngIf = "(i+1) % 2 === 0" class = "w-100"></div>
      </ng-container>

    </div>
  </div>
</div>
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
2 151
1

Ответы 1

Вы никогда не должны подписываться на подписку. Вы можете изменить свой код следующим образом:

this.route.queryParamMap.mergeMap(params => {
    this.category = params.get('category');
    this.cartId = localStorage.getItem('cartId');
    if (this.category) {
       return this.service.allProductNames(this.category, this.cartId);
    } else {
        if (this.cartId === null) {
           this.cartId = -1;
        }
        return this.service.getProducts(this.cartId);    
    }
  }).takeUntil(this.ngUnsubscribe).subscribe(data => this.filteredproducts = data);

Вы должны подписаться на свой queryParams только один раз, и он должен быть в ngOnInit. При добавлении в корзину вы должны учитывать следующие моменты:

  1. Вы уже объявили, что свойство категории использует это в своем методе. Не подписывайтесь на queryParams.
  2. Используйте оператор mergeMap rxjs, чтобы удалить вложенную подписку.
  3. Вложенная подписка не откажется от подписки, когда компонент будет уничтожен.
  4. Вы не должны использовать setTimeout в своей подписке. Используйте оператор debounceTime rxjs

Спасибо :) Я пытаюсь исправить метод addToCart, но с mergeMap, а код внутри не работает .. Моя программа не входит внутрь .. Я следую той же логике .. Внутри ngOnInit все в порядке, но за пределами mergeMap, похоже, не работает :(

Markos 04.10.2018 17:56

я починил .. Большое спасибо за вашу помощь

Markos 04.10.2018 19:01

Другие вопросы по теме