如何在Elm中实现setTimeout行为

如何在Elm中实现setTimeout行为,elm,Elm,我正在用Elm写一个网络游戏,里面有很多与时间相关的事件,我正在寻找一种方法来安排一个特定时间延迟的事件 在JavaScript中,我使用了setTimeout(f,timeout),这显然效果很好,但出于各种原因,我希望避免使用JavaScript代码,而只使用Elm 我知道我可以在特定的时间间隔订阅Tick,并接收时钟信号,但这不是我想要的-我的延迟没有合理的公分母(例如,其中两个延迟为30ms和500ms),我希望避免处理大量不必要的信号 我还遇到了Task和Process——似乎通过使用

我正在用Elm写一个网络游戏,里面有很多与时间相关的事件,我正在寻找一种方法来安排一个特定时间延迟的事件

在JavaScript中,我使用了
setTimeout(f,timeout)
,这显然效果很好,但出于各种原因,我希望避免使用JavaScript代码,而只使用Elm

我知道我可以在特定的时间间隔订阅
Tick
,并接收时钟信号,但这不是我想要的-我的延迟没有合理的公分母(例如,其中两个延迟为30ms和500ms),我希望避免处理大量不必要的信号

我还遇到了
Task
Process
——似乎通过使用它们,我能够以某种方式实现我对
Task.perform failHandler successHandler(Process.sleep Time.second)
的要求

这是可行的,但不是很直观——我的处理程序只是忽略所有可能的输入并发送相同的消息。此外,我并不期望超时会失败,因此创建失败处理程序感觉就像是给库提供信息,这不是我从如此优雅的语言中所期望的


是否有类似于
Task.delayMessage time message
的功能可以完全满足我的需要(在指定的时间后向我发送其消息参数的副本),或者我必须为其制作自己的包装器?

一开始可能不明显的一点是,订阅可以根据模型进行更改。每次更新后都会对其进行有效评估。您可以使用这个事实,再加上模型中的一些字段,来控制什么订阅在任何时候都处于活动状态

下面是一个示例,它允许:

订阅:模型->子消息
订阅模式=
如果model.showCursor
然后是Time.every model.cursorBlinkInterval(始终切换光标)
其他子项无

如果我理解您的担忧,这将克服处理不必要的滴答声的可能性。通过使用
Sub.batch

可以拥有不同时间间隔的多个订阅。如果您希望“每x秒”发生一次事件,则您需要@ChadGilbert所描述的类似订阅的解决方案。(这或多或少类似于javascript的
setInterval()

另一方面,如果您只希望某件事情“在x秒后发生一次”,那么
进程.睡眠
路径就是要走的路。这相当于javascript的
设置超时()
:经过一段时间后,它会做一次事情

你可能需要自己做包装,比如

-- for Elm 0.18
delay : Time -> msg -> Cmd msg
delay time msg =
  Process.sleep time
  |> Task.andThen (always <| Task.succeed msg)
  |> Task.perform identity
——用于Elm 0.18
延迟:时间->消息->命令消息
延迟时间=
睡眠时间
|>Task.and然后(始终为Task.perform identity
使用,例如这样:

---
update msg model =
  case msg of
    NewStuff somethingNew ->
      ...

    Defer somethingNew ->
      model
      ! [ delay (Time.second * 5) <| NewStuff somethingNew ]
---
更新msg模型=
味精案例
NewStuff somethingNew->
...
延迟一些新内容->
模型

![delay(Time.second*5)的更新和简化版本现在是:


使用相同的用法时

Elm 0.19:

要执行一次并延迟:

delay : Float -> msg -> Cmd msg
delay time msg =
  Process.sleep time
  |> Task.andThen (always <| Task.succeed msg)
  |> Task.perform identity

仅供参考,elm lang/core在
任务方面似乎有点不同。请执行
。请参阅@Tosh。事实上,它似乎刚刚得到更新,以支持无故障情况。是否有办法在超时过期之前取消延迟的操作?一种方法是“取消”是在模型中设置一个标志,然后在最终消息的情况下检查该标志(
NewStuff
在上述情况下)编辑:不太有状态的是将模型传递给
NewStuff
,然后对照当前模型进行检查,如果它们不同,则取消。除了取消消息,我同意以不同的方式处理它。并且在
SomethingNew
分支内建立检查,以确定是否仍然需要生成包含消息的新模型。标记In model是最符合逻辑的。您的
update
函数已经可以访问该模型,无需在消息中传递它。理由:严格来说,您的Elm代码无法控制发送给
update
函数的消息流。因此
update
函数应该假设消息可以在任何时间以某种方式传入ny order.@Grav您能给我指一些文档或示例代码,它们与您所描述的内容相符吗?谢谢!我用什么来代替时间呢?时间
似乎不再起作用了?它的第一个参数是
浮点
delay : Float -> msg -> Cmd msg
delay time msg =
  Process.sleep time
  |> Task.andThen (always <| Task.succeed msg)
  |> Task.perform identity
every : Float -> (Posix -> msg) -> Sub msg