我有一个需要按顺序运行的Cmd Msg
列表。我目前正在使用Cmd.batch list
,但似乎所有这些都在同时运行,以便稍后运行的命令不会意识到先前命令应该引入的模型的任何更改。
我正在调查Task.andThen
,但我不太确定这是正确的方向,也不确定如何从Cmd Msg
中制作Task
。我是在正确的轨道还是有更好的方法来做到这一点,也许仍然使用Cmd.batch
?
我目前有两个功能receive : String -> Model -> Cmd Msg
和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)
修改
edit2:我想我可以通过省略我在receive
/ processMsg
中使用模型来简化示例,但我意识到我需要新模型才能形成每个后续消息
我正在尝试使用Task.sequence
和Task.process
,但没有成功。我可以获得第一个成功运行的命令,但我不知道如何扩展它以使所有命令运行:
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
...
我考虑过将processMsg
更改为processMsg : String -> Task String Msg
,但后来我不知道为Task.perform
的第二个参数提供什么。我不确定Task.sequence
是如何形成这一点的,因为当我尝试将其插入管道时我最终会用
List (Task x String) -> Task x (List String) -> Task x (List Msg) -> Cmd (List Msg)
我不知道该怎么做。
答案 0 :(得分:13)
Task.sequence
将确保任务按顺序而不是同时运行。
要从任务中制作Cmd msg
,请使用Task.attempt
或Task.perform
。
修改强>
根据您更新的问题,我认为不需要为此使用任务。听起来你想要将一堆更新链接在一起,这可以通过递归update
函数调用本身来完成。您可以使用List.foldl
为每个后续消息累积模型状态和命令。
以下是我的意思的快速而肮脏的例子:
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 } ! []
您可以保证消息以正确的顺序传递给update
,因为不需要将它包装在使执行顺序模糊的任务中。
以下是gist of this quick 'n dirty example,您可以直接粘贴到http://elm-lang.org/try: