如何链接Cmd Msgs

时间:2016-09-22 00:54:55

标签: elm

我有一个需要按顺序运行的Cmd Msg列表。我目前正在使用Cmd.batch list,但似乎所有这些都在同时运行,以便稍后运行的命令不会意识到先前命令应该引入的模型的任何更改。

我正在调查Task.andThen,但我不太确定这是正确的方向,也不确定如何从Cmd Msg中制作Task。我是在正确的轨道还是有更好的方法来做到这一点,也许仍然使用Cmd.batch

我目前有两个功能receive : String -> Model -> Cmd MsgprocessMsg : 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.sequenceTask.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)

我不知道该怎么做。

1 个答案:

答案 0 :(得分:13)

Task.sequence将确保任务按顺序而不是同时运行。

要从任务中制作Cmd msg,请使用Task.attemptTask.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