typescript tap()与subscribe()设置类属性

tktrz96b  于 2023-01-18  发布在  TypeScript
关注(0)|答案(4)|浏览(340)

我对rxjs很陌生,我只是想知道通过管道传输流并点击它来设置类属性是否可以,或者我应该在订阅中这样做。对我来说,无论哪种方式都有效,只是想知道是否可以按照我认为合适的方式来做,或者有一些我不知道的事情。
typescript 代码演示两种方式:

export class ViewComponent implements OnInit {

  applicant = {};

  constructor(public route: ActivatedRoute, private store: Store<any>) {}

  ngOnInit() {
    this.route.paramMap.pipe(
      switchMap(params => this.store.select(state => state.applicants.entities[params.get('id')])),
      tap(applicant => this.applicant = applicant)
    ).subscribe();
  }
}

对比

export class ViewComponent implements OnInit {

  applicant = {};

  constructor(public route: ActivatedRoute, private store: Store<any>) {}

  ngOnInit() {
    this.route.paramMap.pipe(
      switchMap(params => this.store.select(state => state.applicants.entities[params.get('id')]))
    ).subscribe(applicant => this.applicant = applicant);
  }
}
qq24tv8q

qq24tv8q1#

编辑:忽略这个答案!
这里有一个很好的答案:https://stackoverflow.com/a/50882183/5932590
请参阅JMD下面的评论以了解更多上下文!
问得好。在source code中的tap操作符中,下面的注解很好地概括了它:
此运算符对于调试观察对象以获得正确的值或执行其他副作用非常有用。
注意:这与观察对象上的subscribe不同。如果do返回的观察对象未被订阅,观察者指定的副作用将永远不会发生。do因此只是监视现有的执行,它不会像subscribe那样触发执行。
你可以在tap中运行的任何副作用也可以放在subscribe块中。subscribe表示你打算主动使用源值,因为它说“当这个可观察对象发出时,我想把它的值保存在applicants变量中”。tap操作符主要是用于调试,但它 * 可以 * 用于运行副作用。
一般来说,运行副作用时最好使用subscribe块,使用tap进行调试,但要注意,如果需要,tap可以做更多的事情。

cgh8pdjw

cgh8pdjw2#

tap在将可观察对象与其订阅者分离时非常有用。如果您有一个公开可观察对象的类,则可以使用tap来实现副作用,即当有人正在“侦听”可观察对象时,该类需要执行该副作用。另一方面,当您从另一个类订阅该类时,可以从订阅者的Angular 实现副作用。使用subscribe
使用可观察对象类:

public dummyObservable: Observable<number> = from([1, 2, 3, 4, 5]).pipe(
  // Side effects, executed every time I emit a value
  // I don't know which side effects implements who subscribes to me
  tap( n => console.log("I'm emitting this value:", n) )
);

使用订阅类:

ngOnInit(): void {
  this.dummyService.dummyObservable.subscribe(
    // Side effects, executed every time I receive a value
    // I don't know which side effects implements the observable
    data => console.log("I'm receiving this value: ", data)
  );
}
lvjbypge

lvjbypge3#

Michael Hladky建议你把所有的副作用都放在tap操作符中,他解释了为什么here
我认为这样做通常是一个好主意,因为正如Michael所说,您可以将许多可观察对象合并在一起,并为所有这些对象创建一个订阅。
我不知道这是否会提高性能,但当你想取消订阅时,它肯定会让你更容易。取消订阅是你应该经常做的事情,以避免可能的内存泄漏或其他奇怪的行为。
这种方法的另一个好处是,你可以很容易地暂停、恢复或完成一组观察对象,方法是通过filter或takeWhile这样的操作符,或者通过另一个观察对象进行切换Map,如下所示:

const allMergedObservables$ = merge(obs1, obs2, obs3);
const play$ = new Subject();

play$.asObservable().pipe(
    switchMap(bool => bool ? allMergedObservables$ : EMPTY)
).subscribe();

// Putting 'true' into the play stream activates allMergedObservables$. 
play$.next(true);

// Something happens that makes you want to pause the application,
// for instance the user opens the print dialog box,
// so you issue 'false' in the play stream which in turn stops the
// inner subscription of allMergedObservables$:
play$.next(false);

然而,这取决于您和您喜欢的编程风格。

nwnhqdif

nwnhqdif4#

使用AsyncPipeNgrxPushPipe

对于那些希望使用async管道或ngrxPush管道的用户,您别无选择,只能使用tap操作符
在上面的例子中,我们可以得到类似于

export class ViewComponent implements OnInit {
  
  applicant = {};
  applicant$ = this.route.paramMap.pipe(
      switchMap(params => this.store.select(state => state.applicants.entities[params.get('id')])),
      tap(applicant => this.applicant = applicant)
    )
  constructor(public route: ActivatedRoute, private store: Store<any>) {}

  ngOnInit() { }
}

并且在HTML中
使用AsyncPipe

<ng-container *ngIf='applicant$ | async'>

   ...Some Html code here

</ng-container>

使用NgrxPushPipe(请记住,只有在使用import { ReactiveComponent } from '@ngrx/component'时才有效)

<ng-container *ngIf='applicant$ | ngrxPush'>
 
...Some Html code here

</ng-container>

添加

上述两个管道有助于提高代码的可维护性,并减少/消除由于未订阅的可观察项而导致内存泄漏的风险
上述代码可以简化为

TS文件

export class ViewComponent {
 
  applicant$ = this.route.paramMap.pipe(
      switchMap(params => this.store.select(state => 
        state.applicants.entities[params.get('id')])
      )
    )
  constructor(public route: ActivatedRoute, private store: Store<any>) {}

}

HTML文件

使用AsyncPipe

<ng-container *ngIf='applicant$ | async as applicant'>

   ...Some Html code here

</ng-container>

使用NgrxPushPipe

<ng-container *ngIf='applicant$ | ngrxPush as applicant'>

   ...Some Html code here

</ng-container>

使用NgrxPushPipe

<ng-container *ngIf='applicant$ | ngrxPush as applicant'>

   ...Some Html code here

</ng-container>

使用ngrxLet结构指令(也来自“@ngrx/component”)

<ng-container *ngrxLet='applicant$; let applicant'>

   ...Some Html code here

</ng-container>

相关问题