【问题标题】:Rxjs: Assigning a subject.pipe() to an observable in Angular ngOnInitRxjs:将 subject.pipe() 分配给 Angular ngOnInit 中的可观察对象
【发布时间】:2021-04-05 01:38:28
【问题描述】:

模板有一个输入监听 keyUp 事件。该组件有一个 Observable 和一个 Subject。 Subject 通过管道将字符串值从输入映射到 Stock[] Observable 的操作符。 在每个 keyUp 事件中,Subject 都会发出带有来自输入的新值的下一个事件。

模板:

<div>
<input  name="searchBox"
        [(ngModel)]="searchString"
        placeholder="Search here"
        (keyup)="search()">
</div>

<h2>
     We have found {{ (stocks$ | async )?.length }} stocks!
</h2>
 <app-stock-item *ngFor="let stock of stocks$ | async"
            [stock]="stock"
>

</app-stock-item>       

组件:

import { Component, OnInit } from '@angular/core';
import {Observable} from 'rxjs';
import {StockService} from '../../services/stock.service';
import {Stock} from '../../model/stock';

import {Subject} from 'rxjs';

import {debounceTime,switchMap,distinctUntilChanged,
    startWith, share} from 'rxjs/operators';

@Component({
   selector: 'app-stock-list',
   templateUrl: './stock-list.component.html',
   styleUrls: ['./stock-list.component.css']
})
export class StockListComponent implements OnInit {

  public stocks$!: Observable<Stock[]>;

  public searchString:string = "";

  private searchTerms:Subject<string> = new Subject();

  constructor(private stockService:StockService) { }

  ngOnInit(): void {

  console.log(this.stocks$);

                  // how does this work after ngOnInit is executed?
  this.stocks$ = this.searchTerms.pipe(
                  startWith(this.searchString),
                  debounceTime(500),
                  distinctUntilChanged(),
                  //getStocks returns an Observable of HttpClient
                  switchMap( (query) => this.stockService.getStocks(query)),
                  share()
      );


  }


  search(){

    this.searchTerms.next(this.searchString);

  }

}

如果每次渲染组件时只调用一次 ngOnInit,为什么在 ngOnInit 完成执行后 Subject.pipe() 和 Subject.next() 仍然有效?主题是否在代码中的任何位置被订阅?

【问题讨论】:

  • 之所以有效,是因为您的模板中有两个 AsyncPipe 用法。两者都隐式创建订阅。
  • @miqh 所以当订阅 Observable 时,Subject 也会被订阅?
  • 我认为这些异步管道订阅了stocks$ observable。 stocks$ 的定义恰好基于 searchTerms 主题。换句话说,异步管道不会创建对基础主题的直接订阅——在我看来这也没有意义,除非您在模板中有要显示当前 searchTerms 值的内容(即通过另一个异步管道)。
  • 主题管道中的运算符是否保存在某个地方? ngOnInit 完成后如何不销毁操作符?
  • 这是 observable 定义的一部分——仅仅因为执行离开 ngOnInit() 并不意味着 observable 消失了。 stocks$ 的范围是组件的生命周期。当组件被销毁时,异步管道订阅也会被销毁(如果您阅读了我上面链接的文档)。

标签: angular rxjs


【解决方案1】:

非常简化的图片是:

searchTerms = {
  subscriptionFn: null,
  next: function(query) {
    this.subscriptionFn(query);
  }
};
stocks$ = {value: null};
    
    
ngOnInit() {
  this.searchTerms.subscriptionFn = (query) => this.stockService.getStocks(query).subscribe(value => this.stocks$.value = value);
}

search(){

  this.searchTerms.next(this.searchString);

}

而 html 异步管道将只是 {{stocks$.value}}。 有很多差异 - 例如switchMap 将取消旧请求,当新请求等时,但是~~~这段代码也是这样做的。

【讨论】:

  • 那么subject和observable共享同一个订阅对象?
猜你喜欢
  • 1970-01-01
  • 2018-10-25
  • 2019-07-07
  • 2017-06-11
  • 1970-01-01
  • 2016-06-18
  • 1970-01-01
  • 2022-11-25
  • 2020-08-28
相关资源
最近更新 更多