2016-09-22 17 views
5

Mam listę Cmd Msg s, które należy uruchomić w kolejności. Obecnie używam Cmd.batch list, ale wydaje się, że wszystkie z nich działają jednocześnie, tak że polecenia, które powinny być uruchamiane później, nie są świadome jakichkolwiek zmian w modelu, które powinny zostać wprowadzone wcześniejszymi poleceniami.jak łańcuch Cmd Msgs

Zajmuję się Task.andThen, ale nie jestem całkiem pewny, czy to jest właściwy kierunek lub jak zrobić Cmd Msg z Task. Czy jestem na dobrej drodze, czy jest lepszy sposób na zrobienie tego, być może, który nadal wykorzystuje Cmd.batch?

Obecnie mam dwie funkcje receive : String -> Model -> Cmd Msg i 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) 

edycji

Edit2: Myślałem, że mogę uprościć przykład przez pominięcie, że mogę używać modelu w receive/processMsg ale zdałem sobie sprawę, że potrzebuję nowego modelu, aby utworzyć każdy kolejny komunikat.

Próbuję użyć Task.sequence i Task.process, ale bez powodzenia. Mogę dostać pierwsze polecenie do uruchomienia powodzeniem, ale nie wiem jak to rozwinąć, aby wszystkie polecenia, aby uruchomić:

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 
... 

myślałem o zmianie processMsg do processMsg : String -> Task String Msg ale nie mam pojęcia, co dostarczamy do drugi argument z Task.perform. Nie jestem pewien, jak Task.sequence dane do tego, bo gdy próbuję wstawić go do rury po prostu skończyć z

List (Task x String) -> Task x (List String) -> Task x (List Msg) -> Cmd (List Msg)

którym nie wiem co robić.

Odpowiedz

11

Task.sequence zapewnia, że ​​zadania będą wykonywane kolejno, a nie jednocześnie.

Aby wykonać zadanie Cmd msg, należy użyć Task.attempt lub Task.perform.

Edit

podstawie zaktualizowanego pytanie, ja nie sądzę, że istnieje realna potrzeba używać do tego zadania. Wygląda na to, że chcesz połączyć kilka aktualizacji razem, a to można zrobić, wywołując rekursywnie funkcję update. Możesz użyć List.foldl, aby zebrać stan modelu i polecenia dla każdej kolejnej wiadomości.

Oto szybki i brudny przykładem tego, co mam na myśli:

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 } ! [] 

Masz gwarancję, że wiadomości są przekazywane do update we właściwej kolejności, ponieważ nie ma potrzeby, aby owinąć go w zadaniach, które sprawia, kolejność wykonywania niejednoznaczna.

Oto gist of this quick 'n dirty example który można wkleić bezpośrednio do http://elm-lang.org/try:

+0

Mam twardy czas na zastanawianie się, jak używać 'Task's ... zobacz moje powyższe zmiany. Dzięki – erp

+0

@erp - zaktualizowałem swoją odpowiedź, aby pokazać, jak można to zrobić bez potrzeby wykonywania zadań. Jeśli nie ma prawdziwego powodu, aby korzystać z zadań w tym celu, polecam pójść z czymś podobnym do powyższego. –

+0

Postaram się sprawdzić, czy to działa dla mnie, ale zdałem sobie sprawę, że potrzebuję każdego kolejnego nowego wykresu, aby utworzyć następną 'Msg', więc mój rzeczywisty problem może być bardziej skomplikowany niż początkowo sądziłem. – erp