typescript tap() vs subscribe() 设置类属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/49184754/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
tap() vs subscribe() to set a class property
提问by bulforce
I am very new to rxjs and was just wondering is it ok to setup a class property by piping the stream and tapping it, or it should i do it in the subscribe. To me either way works, just wonder if it is ok to do it as I see fit to my eyes or there is something I am unaware of.
我对 rxjs 非常陌生,只是想知道是否可以通过管道传输流并点击它来设置类属性,或者我应该在订阅中进行设置。对我来说,无论哪种方式都有效,只是想知道是否可以按照我认为适合我的眼睛进行操作,或者有什么我不知道的事情。
Typescript code demonstrating both ways:
两种方式的打字稿代码:
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();
}
}
vs
对比
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);
}
}
回答by vince
Good question. In the source codefor the tap
operator, this comment pretty much sums it up:
好问题。在操作符的源代码中tap
,这个注释几乎总结了它:
This operator is useful for debugging your Observables for the correct values or performing other side effects.
Note: this is different to asubscribe
on the Observable. If the Observable returned bydo
is not subscribed, the side effects specified by the Observer will never happen.do
therefore simply spies on existing execution, it does not trigger an execution to happen likesubscribe
does.
此运算符可用于调试 Observable 以获得正确值或执行其他副作用。
注意:这subscribe
与 Observable 上的a 不同。如果返回的 Observabledo
未被订阅,则永远不会发生 Observer 指定的副作用。do
因此只是监视现有的执行,它不会像subscribe
那样触发执行。
Any side effect you can run in a tap
can probably also be put in the subscribe
block. The subscribe
indicates your intent to actively use the source value since it's saying "when this observable emits, I want to save it's value in the applicants
variable". The tap
operator is mostly there for debugging, but it canbe used to run side effects.
您可以在 a 中运行的任何副作用tap
也可以放入subscribe
块中。该subscribe
说明你的意图,因为它说:“当这个观察到发射,我要保存在它的价值,是积极利用源值applicants
变量”。该tap
运营商主要是有用于调试,但它可以被用来运行副作用。
In general, favor the subscribe
block for running side effects, use tap
for debugging, but be aware that tap
can do more if you need it to.
一般来说,支持subscribe
用于运行副作用的块,tap
用于调试,但请注意,tap
如果需要它可以做更多的事情。
回答by mariogl
tap
is useful when you have the observable separated from its subscriber. If you have a class that exposes an observable, you can use tap
to implement side effects that this class needs to be executed when someone is listeningto the observable. In the other side, when you subscribe to it from another class, you can implement side effects from the subscriber's point of view, using subscribe
.
tap
当您将 observable 与其订阅者分开时,这很有用。如果您有一个公开 observable 的类,您可以使用它tap
来实现当有人在监听observable时需要执行该类的副作用。另一方面,当你从另一个类订阅它时,你可以从订阅者的角度实现副作用,使用subscribe
.
Class with the observable:
与可观察的类:
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) )
);
Class with the subscription:
订阅类:
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)
);
}
回答by Fredrik_Macrobond
Michael Hladky suggests that you put all side effects in the tap operator and he explains why here.
Michael Hladky 建议您将所有副作用都放在 tap 运算符中,他在这里解释了原因。
I think it's generally a good idea to do so, because as Michael says, you can then merge many observables together and create one single subscription for all of them.
我认为这样做通常是一个好主意,因为正如迈克尔所说,然后您可以将许多可观察对象合并在一起,并为所有这些对象创建一个订阅。
I don't know if this improves performance or not, but it definitely makes it easier when you want to unsubscribe to only have one subscription. Unsubscribing is something you always should do to avoid possible memory leaks or other strange behaviors.
我不知道这是否会提高性能,但是当您想取消订阅而只订阅一个时,它肯定会让事情变得更容易。取消订阅是您应该始终做的事情,以避免可能的内存泄漏或其他奇怪的行为。
Another gain from this approach is that you then easily can pause, resume or complete a group of observables by piping it through operators such as filter or takeWhile, or by switchmapping it through another observable like this:
这种方法的另一个好处是,您可以轻松地暂停、恢复或完成一组 observable,方法是通过 filter 或 takeWhile 等运算符对其进行管道传输,或者通过另一个 observable 进行切换映射,如下所示:
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);
However, it's up to you and whatever programming style you prefer.
但是,这取决于您和您喜欢的任何编程风格。