I have a list of Cmd Msg
s that need to be run in order. I'm currently using Cmd.batch list
but it seems like all of them are running simultaneously such that commands that should run later are unaware of any changes to the model the earlier commands should have introduced.
I'm looking into Task.andThen
but am not quite sure if that is the right direction or how to make a Cmd Msg
out of a Task
. Am I on the right track or is there a better way to do this, maybe that still utilizes Cmd.batch
?
I currently have two functions receive : String -> Model -> Cmd Msg
and processMsg : String -> Model -> Cmd Msg
:
receive : String -> Model -> Cmd Msg
receive msg model =
msg |> String.split "&"
|> List.map String.trim
|> List.sort
|> List.map (processMsg model)
|> Cmd.batch
processMsg : String -> Model -> Cmd Msg
... (uses Cmd.Extra.message for Msg -> Cmd Msg)
edit
edit2: I thought I could simplify the example by omitting that I use the model in receive
/processMsg
but I realized that I need the new model in order to form each subsequent message.
I'm trying to use Task.sequence
and Task.process
but to no success. I can get the first command to run successfully but I don't know how to expand this to get all commands to run:
receive : String -> Model -> Cmd Msg
receive msg model =
let
msgs =
msg |> String.split "&"
|> List.map String.trim
|> List.sort
|> List.head
|> Maybe.withDefault "none"
|> Task.succeed
in
Task.perform Oops (processMsg model) msgs
processMsg : String -> Model -> Msg
...
I thought about changing processMsg
to processMsg : String -> Task String Msg
but then I have no idea what to supply for the second argument of Task.perform
. I'm not sure how Task.sequence
figures into this because when I try to insert it into the pipe I just end up with
List (Task x String) -> Task x (List String) -> Task x (List Msg) -> Cmd (List Msg)
which I don't know what to do with.
Task.sequence
will ensure that the tasks run in sequence rather than simultaneously.
To make a Cmd msg
from a task, you use Task.attempt
or Task.perform
.
Edit
Based on your updated question, I don't think there is a real need to use Tasks for this. It sounds like you want to chain a bunch of updates together, and that can be done by having the update
function call itself recursively. You could use List.foldl
to accumulate the model state and commands for each subsequent message.
Here's a quick and dirty example of what I mean:
update msg model =
case msg of
ChainMsgs msgs ->
let
chain msg1 (model1, cmds) =
let (model2, cmds1) = update msg1 model1
in model2 ! [ cmds, cmds1 ]
in
List.foldl chain (model ! []) msgs
_ ->
{ model | message = model.message ++ ", " ++ toString msg } ! []
You are guaranteed that the messages are passed to update
in the correct order, because there's no need to wrap it in tasks which makes order of execution ambiguous.
Here is a gist of this quick 'n dirty example which you can paste directly into http://elm-lang.org/try:
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