我得到了一个使用threepenny-gui库的蛇版本,但我不喜欢手动显式调用newEvent和addStateUpdate,而不是完全基于事件定义行为,例如:
(updates, addUpdate) <- liftIO newEvent
managerB <- accumB initialManager updates
on UI.tick timer $ \_ -> addUpdate $ \manager -> manager'与之相比:
managerB <- accumB initialManager $
UI.tick timer $> \manager -> manager'第二种是更惯用的FRP,因为它定义了一个带有实际事件的行为,而不是创建一个代理事件来通过代理更新。但是当我做这个改变时,它会引起两个问题之一:
managerB (使用RecursiveDo访问timer,如下所定义),则不会呈现任何内容。managerB移到末尾(使用RecursiveDo从DOM元素访问managerB ),则第一次按箭头键时的初始移动会滞后,而框架呈现的方式会很不稳定。我做错了什么吗?我应该如何组织这些事件/行为?
这里的代码差异:https://github.com/brandonchinn178/snake/compare/inline-event-handlers
发布于 2021-10-12 17:58:16
我在存储库中的备用分支上测试过的一个不太好的解决方法是同时使用这两种方法:重新触发tick事件,而不是使用UI.tick timer来定义managerB。
(timeE, fireTime) <- liftIO newEvent
on UI.tick timer $ \_ -> liftIO (fireTime ())
let managerUpdateE =
fmap concatenate . unions $
[ timeE $> getNextManagerState
-- Instead of: UI.tick timer $> getNextManagerState
-- etc.问题似乎是,将UI.tick timer直接插入事件网络会妨碍Threepenny及时发送更新UI所需的JavaScript调用。使用on与fireTime的间接关系(尤其应该意味着timeE发生在UI.tick timer之后)似乎回避了这个问题。一个不那么麻烦的解决方法不是引入timeE,而是在UI.tick timer的处理程序中显式地调用flushCallBuffer;然而,在我的测试中,这大大减少了混乱,但并没有完全消除它。(可能需要相关的背景信息,请参见“三部曲”第191期。)
至于第一次击键的延迟,似乎可以通过将UI.start timer调用移到gui的末尾,在managerB和事件网络的其余部分建立之后消除。
(另外,遵循Graphics.UI.Threepenny.Timer文档的建议并在ghc-options中设置-threaded来编译您的可执行文件可能是个好主意,即使这似乎对您在这里描述的问题没有影响。)
https://stackoverflow.com/questions/69511694
复制相似问题