Angular RxJS:takeUntil()角度分量';s Ngondestory()
tl;dr:基本上我想把Angular的Angular RxJS:takeUntil()角度分量';s Ngondestory(),angular,components,rxjs,rxjs5,Angular,Components,Rxjs,Rxjs5,tl;dr:基本上我想把Angular的Ngondestory和RxjstakeUntil()操作符结合起来可能吗 我有一个角度组件,可以打开几个Rxjs订阅。 当组件被销毁时,需要将其关闭 一个简单的解决方案是: class myComponent { private subscriptionA; private subscriptionB; private subscriptionC; constructor( private serviceA: ServiceA
Ngondestory
和RxjstakeUntil()
操作符结合起来可能吗
我有一个角度组件,可以打开几个Rxjs订阅。
当组件被销毁时,需要将其关闭
一个简单的解决方案是:
class myComponent {
private subscriptionA;
private subscriptionB;
private subscriptionC;
constructor(
private serviceA: ServiceA,
private serviceB: ServiceB,
private serviceC: ServiceC) {}
ngOnInit() {
this.subscriptionA = this.serviceA.subscribe(...);
this.subscriptionB = this.serviceB.subscribe(...);
this.subscriptionC = this.serviceC.subscribe(...);
}
ngOnDestroy() {
this.subscriptionA.unsubscribe();
this.subscriptionB.unsubscribe();
this.subscriptionC.unsubscribe();
}
}
这是可行的,但有点多余。我尤其不喜欢这样
-取消订阅()的unsubscribe()
在其他地方,因此您必须记住它们是链接的。
-组件状态被订阅污染
我更喜欢使用takeUntil()
操作符或类似的方法,使其看起来像这样:
class myComponent {
constructor(
private serviceA: ServiceA,
private serviceB: ServiceB,
private serviceC: ServiceC) {}
ngOnInit() {
const destroy = Observable.fromEvent(???).first();
this.subscriptionA = this.serviceA.subscribe(...).takeUntil(destroy);
this.subscriptionB = this.serviceB.subscribe(...).takeUntil(destroy);
this.subscriptionC = this.serviceC.subscribe(...).takeUntil(destroy);
}
}
const Observable = Rx.Observable;
const Subject = Rx.Subject;
let source = Observable.timer(0, 1000);
let subject = new Subject();
source.takeUntil(subject).subscribe(null, null, () => console.log('complete 1'));
source.takeUntil(subject).subscribe(null, null, () => console.log('complete 2'));
source.takeUntil(subject).subscribe(null, null, () => console.log('complete 3'));
setTimeout(() => {
subject.next();
}, 3000);
是否存在销毁事件或类似事件,允许我使用takeUntil()
或其他类似方法来简化组件体系结构?
我意识到我可以自己在构造函数中创建一个事件,或者在
ngondstroy()
中触发某个事件,但这最终不会使阅读变得简单。您可以利用ReplaySubject
实现这一点:
编辑:与RxJS 6.x不同:
注意pipe()
方法的使用
class myComponent {
private destroyed$: ReplaySubject<boolean> = new ReplaySubject(1);
constructor(
private serviceA: ServiceA,
private serviceB: ServiceB,
private serviceC: ServiceC) {}
ngOnInit() {
this.serviceA
.pipe(takeUntil(this.destroyed$))
.subscribe(...);
this.serviceB
.pipe(takeUntil(this.destroyed$))
.subscribe(...);
this.serviceC
.pipe(takeUntil(this.destroyed$))
.subscribe(...);
}
ngOnDestroy() {
this.destroyed$.next(true);
this.destroyed$.complete();
}
}
类myComponent{
private destromed$:ReplaySubject=新ReplaySubject(1);
建造师(
私人服务a:serviceA,
私人服务b:serviceB,
私人服务c:serviceC{}
恩戈尼尼特(){
这是服务
.pipe(takeUntil(此.destromed$))
.认购(……);
这是服务B
.pipe(takeUntil(此.destromed$))
.认购(……);
这是我的服务
.pipe(takeUntil(此.destromed$))
.认购(……);
}
恩贡德斯特罗(){
此.next(true)已销毁$;
此.complete$.complete();
}
}
这仅适用于RxJS 5.x及更早版本:
class myComponentOld {
private destroyed$: ReplaySubject<boolean> = new ReplaySubject(1);
constructor(private serviceA: ServiceA) {}
ngOnInit() {
this.serviceA
.takeUntil(this.destroyed$)
.subscribe(...);
}
ngOnDestroy() {
this.destroyed$.next(true);
this.destroyed$.complete();
}
}
类myComponentOld{
private destromed$:ReplaySubject=新ReplaySubject(1);
构造函数(私有serviceA:serviceA){}
恩戈尼尼特(){
这是服务
.takeUntil(此.destromed$)
.认购(……);
}
恩贡德斯特罗(){
此.next(true)已销毁$;
此.complete$.complete();
}
}
好吧,这取决于您关闭订阅的意思。基本上有两种方法可以做到这一点:
takeWhile()
)takeWhile()
时,您让操作员发送complete
通知,并将其传播给您的观察者。因此,如果您定义:
...
.subscribe(..., ..., () => doWhatever());
然后,当您使用例如takeWhile()
完成链时,将调用doWhatever()
函数
例如,它可能看起来像这样:
class myComponent {
constructor(
private serviceA: ServiceA,
private serviceB: ServiceB,
private serviceC: ServiceC) {}
ngOnInit() {
const destroy = Observable.fromEvent(???).first();
this.subscriptionA = this.serviceA.subscribe(...).takeUntil(destroy);
this.subscriptionB = this.serviceB.subscribe(...).takeUntil(destroy);
this.subscriptionC = this.serviceC.subscribe(...).takeUntil(destroy);
}
}
const Observable = Rx.Observable;
const Subject = Rx.Subject;
let source = Observable.timer(0, 1000);
let subject = new Subject();
source.takeUntil(subject).subscribe(null, null, () => console.log('complete 1'));
source.takeUntil(subject).subscribe(null, null, () => console.log('complete 2'));
source.takeUntil(subject).subscribe(null, null, () => console.log('complete 3'));
setTimeout(() => {
subject.next();
}, 3000);
3s后,将调用所有完整的回调
另一方面,当你取消订阅时,你是在说你不再对来源产生的项目感兴趣。然而,这并不意味着源代码必须完成。你只是不在乎而已
这意味着您可以从.subscribe(…)
呼叫中收集所有订阅
并立即取消订阅:
let subscriptions = new Rx.Subscription();
let source = Observable.timer(0, 1000);
subscriptions.add(source.subscribe(null, null, () => console.log('complete 1')));
subscriptions.add(source.subscribe(null, null, () => console.log('complete 2')));
subscriptions.add(source.subscribe(null, null, () => console.log('complete 3')));
setTimeout(() => {
subscriptions.unsubscribe();
}, 3000);
现在,在3s延迟之后,不会向控制台打印任何内容,因为我们取消了订阅,并且没有调用任何完整的回调
因此,您想要使用什么取决于您和您的用例。请注意,取消订阅与完成并不相同,尽管我猜在您的情况下这并不重要。使用npm软件包中的
componentdestromed()
函数是目前为止最简单的使用方法,直到:
@组件({
选择器:“foo”,
templateUrl:“./foo.component.html”
})
导出类FooComponent实现OnInit、OnDestroy{
恩戈尼尼特(){
可观测间隔(1000)
.takeUntil(componentDestroyed(this))/如果您的组件直接绑定到路由,您可以通过利用避免添加状态。这样,一旦您离开该组件,它将自动为您清理其订阅
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { MyService } from './my.service';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/takeUntil';
@Component({
...
})
export class ExampleComopnent implements OnInit {
constructor(private router: Router, private myService: MyService) {
}
ngOnInit() {
this.myService.methodA()
.takeUntil(this.router.events)
.subscribe(dataA => {
...
});
this.myService.methodB()
.takeUntil(this.router.events)
.subscribe(dataB => {
...
});
}
}
注意:这个简单的示例不考虑受保护的路由或取消的路由导航。如果有可能触发路由导航,但路由导航被取消,则需要过滤路由器事件,以便在适当的点触发它-例如,在检查后或导航完成后埃特
this.myService.methodA()
.takeUntil(this.router.events.filter(e => e instanceOf NavigationEnd))
.subscribe(dataA => {
...
});
创建基类
import { Subject } from 'rxjs/Rx';
import { OnDestroy } from '@angular/core';
export abstract class Base implements OnDestroy {
protected componentDestroyed$: Subject<any>;
constructor() {
this.componentDestroyed$ = new Subject<void>();
const destroyFunc = this.ngOnDestroy;
this.ngOnDestroy = () => {
destroyFunc.bind(this)();
this.componentDestroyed$.next();
this.componentDestroyed$.complete();
};
}
// placeholder of ngOnDestroy. no need to do super() call of extended class.
public ngOnDestroy() {
// no-op
}
}
当你订阅时
service.takeUntil(this.componentDestroyed$
.subscribe(...)
这是一个全局级别的更改,无论何时您想要在整个项目中使用相同的方法进行订阅。在任何需要的更改中,您都可以在基类中进行修改可能值得注意的是,不应该启动流,流必须直接从组件内完成-任何关键操作都应该通过服务完成,这是不允许的因为大多数都是开放式的,组件在某一点上会停止监听。但我绝对认为,从原则上讲,取消订阅可能是在这里应用的更好模式,因为这就是T应该是逻辑上发生的。我会考虑的。谢谢!考虑<代码>直到(RX.可观察的。计时器(3000))
在流中。事实上,使用takeUntil
可以完成,而使用unsubscribe
可以取消。从某种程度上说,这不是我想要的——我想避免在组件中创建额外的状态工件(销毁$
)然后从ngondestory
触发它。但是我在看了更多之后才意识到,没有语法糖分可以解决这个问题。这肯定已经是一个比存储所有订阅更好的解决方案了。谢谢!angular团队已经讨论了如何使destroy事件更容易被用户访问xj