Javascript 订阅主题完成后取消订阅

Javascript 订阅主题完成后取消订阅,javascript,typescript,rxjs,Javascript,Typescript,Rxjs,我有一个主题订阅了一个可观察的事件监听器(fromEvent)。单击“停止”按钮时,主题完成,事件侦听器应被删除。目前,我正在跟踪订阅并取消订阅,这也会删除事件侦听器: const{fromEvent,Subject}=rxjs const{map}=rxjs.operators 常量主题=新主题() subject.subscribe(()=>console.log('focused')) const sub=fromEvent(document.querySelector('input')

我有一个主题订阅了一个可观察的事件监听器(
fromEvent
)。单击“停止”按钮时,主题完成,事件侦听器应被删除。目前,我正在跟踪订阅并取消订阅,这也会删除事件侦听器:

const{fromEvent,Subject}=rxjs
const{map}=rxjs.operators
常量主题=新主题()
subject.subscribe(()=>console.log('focused'))
const sub=fromEvent(document.querySelector('input'),'focus')。subscribe(subject)
document.querySelector('button')。onclick=()=>{
//这是我想要避免的
取消订阅;
subject.complete();
}


停止
考虑扩展
主题
类以通知其取消订阅/错误/完成,如下所示:

类NotifyStateSubject扩展了Subject{
公共停止=新主题();
私有通知():无效{
this.stopped.next();
此。已停止。取消订阅();
}
公共错误(错误:任意):无效{
this.notify();
超级错误(err)
}
public complete():void{
this.notify();
super.complete()
}
公共取消订阅():无效{
this.notify();
super.unsubscribe();
}
}
然后按如下方式使用:

fromEvent(...).pipe(takeUntil(subject.stopped$)).subscribe(subject)

不是很优雅,但创造了一个新的可观察的,在主题作品完成时发出:

fromEvent(...).pipe(
  takeUntil(
    new Observable((subscriber) =>
      this._trackedInteractions$?.subscribe({ complete: () => subscriber.next() })
    )
  )
).subscribe(subject)

你想得太多了,这就是你所需要的:

const stop$ = fromEvent(document.querySelector('button'), 'click');

fromEvent(document.querySelector('input'), 'focus').pipe(takeUntil(stop$)).subscribe(subject)
takeUntil
的完成将向下传播到订阅的主题。所有订阅和事件侦听器都将以单击按钮结束

唯一不会发生的事情是,如果主题以按钮点击以外的方式完成,那么您的输入事件仍将触发,尽管订阅者将不再收听。完成会向下游传播,但不会向上游传播

或者,创建新的操作员非常容易(套用您的解决方案):

可以简单地使用以下内容:

fromEvent(document.querySelector('input'), 'focus').pipe(takeUntilComplete(subject)).subscribe(subject)

有趣的解决方案!谢谢你的回答。同时,我发现了一个不同的解决方案,我添加了完整性(没有双关语;-))。没有什么比拥有一个
takenuntlcomplete
操作符更优雅的了。谢谢你的回答!我试着选择一个非常简单的例子,但我可能过于简单化了。在我的实际用例中,我没有被点击的按钮;订阅以一种不同的、更复杂的方式完成。对不起,我的问题没有说清楚。我会编辑它的。好吧,我加了一句,你可以自己做一个操作员
fromEvent(document.querySelector('input'), 'focus').pipe(takeUntilComplete(subject)).subscribe(subject)