代码之家  ›  专栏  ›  技术社区  ›  koque

为什么我的RxJs主题没有按预期工作?

  •  0
  • koque  · 技术社区  · 6 月前

    ProductGalleryComponent.html迭代产品。每个图像的点击事件调用setSelectedProduct函数,将点击的产品传递给它。

    <div class="row py-3 px-2" style="background: #f5f6f8">
      <div
        class="col d-flex flex-column col-12 col-md-4 col-lg-3 mb-4 gallery-img-col"
        *ngFor="let product of products"
      >
        <img
          class="gallery-img"
          src="assets/img/{{ product.images[0] }}"
          (click)="setSelectedProduct(product)"
        />
      </div>
    </div>
    

    ProductGalleryComponent.ts的setSelectedProduct函数调用ProductGalleryService的setSelectedPRroduct函数,传递所选产品。然后导航到SelectedProductComponent。

    public setSelectedProduct = (product: ProductModel) => {
        this.productGalleryService.setSelectedProduct(product);
        this.router.navigateByUrl('/selected-product');
      }
    

    ProductGalleryService声明一个主题和该主题的可观察对象。在setSelecedProduct函数中,它调用主题的下一个函数,将所选产品传递给它:

    export class ProductGalleryService {
        public selectedProductSubject = new Subject<ProductModel>();
        selectedProductSubject$ = this.selectedProductSubject.asObservable();
    
        public setSelectedProduct = (product: ProductModel) => {
            this.selectedProductSubject.next(product);
        }
    }
    

    SelectedProductComponent通过构造函数订阅ProductGalleryService的选定ProductSubject。预计会收到ProductGalleryService.selectdProductSubject广播的产品,但从未收到该产品。

    export class SelectedProductComponent {        
        private productGalleryService = inject(ProductGalleryService)
    
        constructor() {
            this.setSelectedProduct()
        }
    
      private setSelectedProduct = () => {
        this.productGalleryService.selectedProductSubject$.subscribe((product) => {
          this.selectedProduct = product;
          console.log('selectedProductSubject.selectedProduct', this.selectedProduct)
        })
      }
    }
    
    2 回复  |  直到 6 月前
        1
  •  3
  •   Vikas RyanSand20    6 月前

    我相信在SelectedProductComponent订阅之前,ProductGalleryService.selectedProductSubject$subject已经发出。

    如何解决这个问题?

    RxJS提供了另一种类型的主题——回放主题。 订阅ReplaySubject时,它将重新发出任何先前推送的值。 ReplaySubject有一个缓冲区大小,可以存储和重新发射多少项目。对于你的用例,我相信你只关心最后一个,所以BufferSize是1。

    public selectedProductSubject = new ReplaySubject<ProductModel>(1);

    1. Subject vs BehaviourSubject vs ReplaySubject
    2. How to get current value of RxJS Subject or Observable?
        2
  •  0
  •   RyanSand20    6 月前

    您可以尝试使用Angular AsyncPipe自动处理订阅/取消订阅。这对于将Observables绑定到模板非常有用。

    而不是:

    • 创建局部变量
    • 订阅observable\
    • 在Emit上,将发出的值存储在局部变量中

    你会:

    • 将可观测值存储为局部变量
    • 使用异步管道绑定到模板中的可观察对象
    <div *ngIf"selectedProduct$ | async as selectedProduct">
      <h1>{{ selectedProduct.name }}</h1>
    </div>
    

    这还有一个额外的好处,即自动取消订阅。当您的组件被销毁时,您总是希望关闭订阅。在你的例子中,这还没有完成。这不是你的主要问题,而是另一个需要研究的问题。