You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RXJS如何实现点击按钮取消订阅且可通过其他按钮重新订阅

RxJS 按钮控制订阅启停实现方案

原有写法存在两个核心问题:

  1. 嵌套订阅会导致内部count3的订阅不受外层click1订阅的管理,即便取消click1的订阅,count3仍然会持续触发回调
  2. sub.unsubscribe()没有绑定到button2的点击事件回调中,只会在代码初始化时执行一次

核心实现逻辑

  • 声明变量存储计数流的活跃订阅实例,避免重复订阅
  • 点击第一个按钮时,先销毁已存在的订阅,再生成新的订阅存储到变量中
  • 点击第二个按钮时,调用存储的订阅实例的unsubscribe方法销毁订阅,并清空存储变量

基础实现(命令式,逻辑直观)

import { mapTo, scan } from 'rxjs/operators'
import { fromEvent, Subscription } from 'rxjs'

const button1 = document.getElementById("but1")
const button2 = document.getElementById("but2")
const button3 = document.getElementById("but3")

const d = document.getElementById("d")
const p3 = document.createElement("p")
d?.appendChild(p3)

// 存储count3的活跃订阅实例
let count3Sub: Subscription | null = null

// 按钮3的计数逻辑
const click3 = fromEvent(button3, 'click')
const three = click3.pipe(mapTo(1))
const count3 = three.pipe(scan((acc, val) => acc + val, 0))

// 按钮1点击:开启订阅
fromEvent(button1, 'click').subscribe(() => {
  // 先销毁已存在的订阅,避免重复触发回调
  if (count3Sub) count3Sub.unsubscribe()
  count3Sub = count3.subscribe(x => p3.innerHTML = `Click count: ${x}`)
})

// 按钮2点击:取消订阅
fromEvent(button2, 'click').subscribe(() => {
  if (count3Sub) {
    count3Sub.unsubscribe()
    count3Sub = null
  }
})

进阶实现(RxJS 声明式风格)

无需手动维护订阅变量,通过RxJS内置操作符自动管理流生命周期,更符合响应式编程规范:

import { mapTo, scan, takeUntil, switchMap } from 'rxjs/operators'
import { fromEvent, Subject } from 'rxjs'

const button1 = document.getElementById("but1")
const button2 = document.getElementById("but2")
const button3 = document.getElementById("but3")

const d = document.getElementById("d")
const p3 = document.createElement("p")
d?.appendChild(p3)

// 停止信号发射器
const stop$ = new Subject<void>()

// 按钮2点击触发停止信号
fromEvent(button2, 'click').subscribe(() => stop$.next())

// 按钮3计数流
const count3$ = fromEvent(button3, 'click').pipe(
  mapTo(1),
  scan((acc, val) => acc + val, 0)
)

// 按钮1点击时切换到计数流,直到收到停止信号自动终止
fromEvent(button1, 'click').pipe(
  switchMap(() => count3$.pipe(takeUntil(stop$)))
).subscribe(x => p3.innerHTML = `Click count: ${x}`)

内容的提问来源于stack exchange,提问作者Matthew Kna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 00:24:04