Loading some things in parallel into a record

I think I would do something like this (untested):

type alias Things =
    { thing1 : Thing
    , thing2 : Thing
    , thing3 : Thing
    }

type alias Responses =
    { thing1 : Maybe Thing -- or perhaps 'RemoteData Thing'
    , thing2 : Maybe Thing
    , thing3 : Maybe Thing
    }

type Model
    = Loading Responses
    | Loaded Things
    | Error String

type Msg
    = GotThing1 (Result String Thing)
    | GotThing2 (Result String Thing)
    | GotThing3 (Result String Thing)

init : () -> ( Model, Cmd Msg )
init () =
    ( Loading
        { thing1 = Nothing
        , thing2 = Nothing
        , thing3 = Nothing
        }
    , Cmd.batch
        [ getThing1
        , getThing2
        , getThing3
        ]
    )

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case model of
        Error message ->
            ( model, Cmd.none )

        Loaded things ->
            ( model, Cmd.none )

        Loading responses ->
            case msg of
                GotThing1 (Err message) ->
                    ( Error message, Cmd.none )
        
                GotThing1 (Ok thing1) ->
                    checkIfLoaded { responses | thing1 = Just thing1 }

                GotThing2 (Err message) ->
                    ( Error message, Cmd.none )
        
                GotThing2 (Ok thing2) ->
                    checkIfLoaded { responses | thing2 = Just thing2 }

                GotThing3 (Err message) ->
                    ( Error message, Cmd.none )
        
                GotThing3 (Ok thing3) ->
                    checkIfLoaded { responses | thing3 = Just thing3 }

            
checkIfLoaded : Responses -> ( Model, Cmd Msg )
checkIfLoaded results =
    case Maybe.map3 Things results.thing1 results.thing2 results.thing3 of
        Just things ->
            ( Loaded things, Cmd.none )

        Nothing ->
            ( Loading results, Cmd.none )

This avoids the counter and the string keys, and has the advantage of extending nicely to the case where thing1, thing2 and thing3 are different types.

5 Likes