An updated and simplified version of @wintvelt's answer is now:
delay : Time.Time -> msg -> Cmd msg
delay time msg =
Process.sleep time
|> Task.perform (\_ -> msg)
with the same usage
One thing that may not be obvious at first is the fact that subscriptions can change based on the model. They are effectively evaluated after every update. You can use this fact, coupled with some fields in your model, to control what subscriptions are active at any time.
Here is an example that allows for a variable cursor blink interval:
subscriptions : Model -> Sub Msg
subscriptions model =
if model.showCursor
then Time.every model.cursorBlinkInterval (always ToggleCursor)
else Sub.none
If I understand your concerns, this should overcome the potential for handling unnecessary ticks. You can have multiple subscriptions of different intervals by using Sub.batch
.
If you want something to happen "every x seconds", then a subscription like solution, as described by @ChadGilbert is what you need. (which is more or less like javascript's setInterval()
.
If, on the other hand you want something to happen only "once, after x seconds", then Process.sleep
route is the way to go. This is the equivalent of javascript's setTimeOut()
: after some time has passed, it does something once.
You probably have to make your own wrapper for it. Something like
-- for Elm 0.18
delay : Time -> msg -> Cmd msg
delay time msg =
Process.sleep time
|> Task.andThen (always <| Task.succeed msg)
|> Task.perform identity
To use e.g. like this:
---
update msg model =
case msg of
NewStuff somethingNew ->
...
Defer somethingNew ->
model
! [ delay (Time.second * 5) <| NewStuff somethingNew ]
Elm 0.19:
To execute once and delay:
delay : Float -> msg -> Cmd msg
delay time msg =
Process.sleep time
|> Task.andThen (always <| Task.succeed msg)
|> Task.perform identity
To execute a repeating task:
every : Float -> (Posix -> msg) -> Sub msg
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With