如何链接命令消息
how to chain Cmd Msgs
我有一个 Cmd Msg
的列表,需要按顺序 运行。我目前正在使用 Cmd.batch list
,但似乎所有这些都在同时 运行,因此以后应该 运行 的命令不知道早期命令应该对模型进行的任何更改.
我正在研究 Task.andThen
,但不太确定这是否是正确的方向或如何从 Task
中创建 Cmd Msg
。我是在正确的轨道上还是有更好的方法来做到这一点,也许仍然利用 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)
我不知道该怎么办。
Task.sequence
将确保任务 运行 按顺序而不是同时进行。
要从任务中创建 Cmd msg
,您可以使用 Task.attempt
or Task.perform
。
编辑
根据您更新后的问题,我认为没有必要为此使用 Tasks。听起来您想将一堆更新链接在一起,这可以通过让 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 which you can paste directly into http://elm-lang.org/try:
我有一个 Cmd Msg
的列表,需要按顺序 运行。我目前正在使用 Cmd.batch list
,但似乎所有这些都在同时 运行,因此以后应该 运行 的命令不知道早期命令应该对模型进行的任何更改.
我正在研究 Task.andThen
,但不太确定这是否是正确的方向或如何从 Task
中创建 Cmd Msg
。我是在正确的轨道上还是有更好的方法来做到这一点,也许仍然利用 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)
我不知道该怎么办。
Task.sequence
将确保任务 运行 按顺序而不是同时进行。
要从任务中创建 Cmd msg
,您可以使用 Task.attempt
or Task.perform
。
编辑
根据您更新后的问题,我认为没有必要为此使用 Tasks。听起来您想将一堆更新链接在一起,这可以通过让 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 which you can paste directly into http://elm-lang.org/try: