javascript - 根据反应式编程启动和停止计数器
问题描述
我有两个按钮,一个按钮初始化计数器,另一个按钮停止计数器。在声明式编程之后,我根据命令式编程实现了一个函数,并用 observables 实现了另一个函数。
但是,我对声明式的代码并不满意,因为它有副作用和全局参数。
有没有办法根据功能反应式编程来实现这个功能而没有副作用和全局参数?
function exercise_pause_play_observable__imperative() {
const btnStart = document.querySelector('#btnStart');
const btnStop = document.querySelector('#btnStop');
const timer1 = document.querySelector('#timer1') as HTMLDivElement;
let isEnabled = false;
let cant = 0;
let int1: number;
btnStart.addEventListener('click', () => {
if (!isEnabled) {
isEnabled = true;
int1 = setInterval(() => {
cant++;
timer1.textContent = cant.toString();
}, 1000)
}
});
btnStop.addEventListener('click', () => {
isEnabled = false;
clearInterval(int1);
});
}
function exercise_pause_play_observable__declarative() {
const btnStart = document.querySelector('#btnStart');
const btnStop = document.querySelector('#btnStop');
const timer1 = document.querySelector('#timer1') as HTMLDivElement;
let isEnabled = false;
let cant = 0;
let int1: number;
const clickStart$ = fromEvent(btnStart, 'click').pipe(
tap(e => {
if (!isEnabled) {
isEnabled = true;
int1 = setInterval(() => {
cant++;
timer1.textContent = cant.toString();
}, 1000);
}
})
);
const clickStop$ = fromEvent(btnStop, 'click').pipe(
tap(e => {
isEnabled = false;
clearInterval(int1);
})
);
merge(clickStart$, clickStop$);
}
HTML
<body>
<button id="btnStart">START</button>
<button id="btnStop">STOP</button>
<div id="timer1"></div>
<script src="/bundle.js"></script>
</body>
解决方案
使用一个被称为 stop$ 的主题与 takeUntil 取消的间隔。
const { Subject, fromEvent, interval } = rxjs;
const { takeUntil } = rxjs.operators;
const stop$ = new Subject();
fromEvent(document.getElementById('btnStart'), 'click').subscribe(() => {
stop$.next(); // If restarting make sure the old one is cancelled
const timerDiv = document.getElementById('timer1');
timerDiv.innerText = '';
interval(1000).pipe(takeUntil(stop$)).subscribe(val => {
timerDiv.innerText = (val + 1);
});
});
fromEvent(document.getElementById('btnStop'), 'click').subscribe(() => {
stop$.next();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.min.js"></script>
<button id="btnStart">START</button>
<button id="btnStop">STOP</button>
<div id="timer1"></div>
推荐阅读
- python - 仅从数据框中获取数字
- html - 如何使模态在其父 div 之外打开
- javascript - 将从本地机器加载的文件数组作为原始数据发送到我的服务器
- ios - 我是否被迫使用 Apple 应用内购买 API
- ssrs-2012 - 日期在今天和提前 7 天之间时的颜色填充表达式
- python - 尽管有 try-except 块,Python 脚本仍以退出代码 255 退出
- python - 用于组织 matplotlib 地图的 CSV 文件阅读器
- kotlin - 赋值不是表达式,在此上下文中只允许使用表达式
- git - 大型 Bitbucket 存储库 | 将旧的提交拆分到另一个仓库
- php - PHP比较由CSV制成的多维数组中的键/值