处理太多状态
deal with too many state
我的问题很难解释,我会尽量简单地解释一下:
我试着在这个网站上重现一个像这个计时器的计时器:https://cstimer.net/
我遇到的问题是:我必须处理许多 "states" 和许多事件:
我的活动类型是:
计时未启动 -> 我按下 "Space" -> 颜色变为橙色 -> 500 毫秒后 -> 计时变为绿色 -> 我释放 space -> 计时开始 -> 我按下space -> 计时停止
我会编写执行此操作的代码。问题是我的代码因为太多"if".
变得很复杂
if (!chronoIsStarted and SpaceIsPressed) { chrono.color = orange }
if (lastKeyDown - lastKeyUp >= 500 and !chronoIsStarted) { chrono.color = green }
if (keyup == space and lastKeyDown - lastKeyUp >= 500) { chono.start(); }
...
...
这太可怕了,因为我必须有标志变量来防止 chrono 在启动后直接停止。
我正在寻找一种正确管理它的方法。
听说过有限机状态,不知道是不是一个好的解决方案。
目前,我使用 react / redux 和 jquery 来处理事件,但我可以添加任何有帮助的库。
谢谢你
看看RxJS。 RxJS 是一个响应式库,允许您操作异步流。在您的特定示例中,它可能有助于保持您的代码声明性并防止它被全局状态弄乱。
有关介绍,请在此处查看 egghead.io 课程:https://egghead.io/lessons/rxjs-what-is-rxjs
或查看响应式编程简介:https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
例如在你的情况下,看看这个 fiddle 你可以从中做出更复杂的例子:http://jsfiddle.net/bryanph/5rkbxgtj/
// press space for clickSpace event
// hold space for holdSpace event
var chrono = {
isStarted: false
}
document.body.style.backgroundColor = "red"
var spaceUp = Rx.Observable.fromEvent(document.body, 'keyup')
.filter(x => x.keyCode === 32)
var spaceDown = Rx.Observable.fromEvent(document.body, 'keydown')
.filter(e => e.keyCode === 32)
.filter(e => !e.repeat)
.partition(x => chrono.isStarted)
var chronoStarted = spaceDown[0];
var chronoStopped = spaceDown[1];
var clickSpace = chronoStopped.flatMap(function(e) {
return spaceUp.timeout(200, Rx.Observable.empty())
})
var holdSpace = chronoStopped
.flatMap(function(e) {
return Rx.Observable
.return(e)
.delay(500)
.takeUntil(spaceUp)
.take(1)
})
clickSpace.subscribe(function(x) {
document.body.style.backgroundColor = "orange"
})
holdSpace.subscribe(function(x) {
console.log('called')
document.body.style.backgroundColor = "green"
})
我的问题很难解释,我会尽量简单地解释一下:
我试着在这个网站上重现一个像这个计时器的计时器:https://cstimer.net/
我遇到的问题是:我必须处理许多 "states" 和许多事件:
我的活动类型是:
计时未启动 -> 我按下 "Space" -> 颜色变为橙色 -> 500 毫秒后 -> 计时变为绿色 -> 我释放 space -> 计时开始 -> 我按下space -> 计时停止
我会编写执行此操作的代码。问题是我的代码因为太多"if".
变得很复杂if (!chronoIsStarted and SpaceIsPressed) { chrono.color = orange }
if (lastKeyDown - lastKeyUp >= 500 and !chronoIsStarted) { chrono.color = green }
if (keyup == space and lastKeyDown - lastKeyUp >= 500) { chono.start(); }
...
...
这太可怕了,因为我必须有标志变量来防止 chrono 在启动后直接停止。
我正在寻找一种正确管理它的方法。
听说过有限机状态,不知道是不是一个好的解决方案。
目前,我使用 react / redux 和 jquery 来处理事件,但我可以添加任何有帮助的库。
谢谢你
看看RxJS。 RxJS 是一个响应式库,允许您操作异步流。在您的特定示例中,它可能有助于保持您的代码声明性并防止它被全局状态弄乱。
有关介绍,请在此处查看 egghead.io 课程:https://egghead.io/lessons/rxjs-what-is-rxjs
或查看响应式编程简介:https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
例如在你的情况下,看看这个 fiddle 你可以从中做出更复杂的例子:http://jsfiddle.net/bryanph/5rkbxgtj/
// press space for clickSpace event
// hold space for holdSpace event
var chrono = {
isStarted: false
}
document.body.style.backgroundColor = "red"
var spaceUp = Rx.Observable.fromEvent(document.body, 'keyup')
.filter(x => x.keyCode === 32)
var spaceDown = Rx.Observable.fromEvent(document.body, 'keydown')
.filter(e => e.keyCode === 32)
.filter(e => !e.repeat)
.partition(x => chrono.isStarted)
var chronoStarted = spaceDown[0];
var chronoStopped = spaceDown[1];
var clickSpace = chronoStopped.flatMap(function(e) {
return spaceUp.timeout(200, Rx.Observable.empty())
})
var holdSpace = chronoStopped
.flatMap(function(e) {
return Rx.Observable
.return(e)
.delay(500)
.takeUntil(spaceUp)
.take(1)
})
clickSpace.subscribe(function(x) {
document.body.style.backgroundColor = "orange"
})
holdSpace.subscribe(function(x) {
console.log('called')
document.body.style.backgroundColor = "green"
})