Skip to content

Instantly share code, notes, and snippets.

@cobalamin
Created August 24, 2016 07:47
Show Gist options
  • Select an option

  • Save cobalamin/9ce56dcd6e3da7f30f1f0ba58b1b9874 to your computer and use it in GitHub Desktop.

Select an option

Save cobalamin/9ce56dcd6e3da7f30f1f0ba58b1b9874 to your computer and use it in GitHub Desktop.
module FetchParallel exposing (..)
import Html exposing (Html, div, text, ul, li)
import Html.App exposing (program)
import Task
import Http
import Json.Decode as Json
import Json.Decode exposing ((:=))
import Dict exposing (Dict, fromList, toList)
import ZZZFetchJSON exposing (..)
-- MODEL
type alias Comment =
{ body : String }
type alias Post =
{ body : String
, comments : List Comment
}
type alias User =
{ name : String
, username : String
, posts : List Post
}
type alias Intermediate =
{ users : Maybe (List JsonUser)
, posts : Maybe (List JsonPost)
, comments : Maybe (List JsonComment)
}
emptyIntermediate : Intermediate
emptyIntermediate =
{ users = Nothing
, posts = Nothing
, comments = Nothing
}
type alias Model =
{ users : Maybe (Dict Int User)
, intermediate : Intermediate
}
-- MAIN
main =
program
{ init = init
, subscriptions = always Sub.none
, update = update
, view = view
}
-- MESSAGE
type Msg
= UsersFetched (List JsonUser)
| PostsFetched (List JsonPost)
| CommentsFetched (List JsonComment)
-- INIT
die : a -> b
die _ =
Debug.crash "dead"
init : ( Model, Cmd Msg )
init =
( { users = Nothing
, intermediate = emptyIntermediate
}
, Cmd.batch
[ Task.perform die UsersFetched (Http.get (Json.list userDecoder) usersUrl)
, Task.perform die PostsFetched (Http.get (Json.list postDecoder) postsUrl)
, Task.perform die CommentsFetched (Http.get (Json.list commentDecoder) commentsUrl)
]
)
-- UPDATE
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
UsersFetched users ->
let
intermediate =
model.intermediate
in
tryCombine { model | intermediate = { intermediate | users = Just users } } ! []
PostsFetched posts ->
let
intermediate =
model.intermediate
in
tryCombine { model | intermediate = { intermediate | posts = Just posts } } ! []
CommentsFetched comments ->
let
intermediate =
model.intermediate
in
tryCombine { model | intermediate = { intermediate | comments = Just comments } } ! []
tryCombine : Model -> Model
tryCombine ({ intermediate } as model) =
{ model | users = Maybe.map3 combine intermediate.users intermediate.posts intermediate.comments }
-- THE CODE AFTER THIS LINE CAN BE IGNORED FOR THIS DISCUSSION AND IT IS BAD. THANKS :D
--
-- VIEW
view : Model -> Html Msg
view model =
case model.users of
Just users ->
div []
[ ul [] <|
List.map
(\( id, u ) ->
li []
[ text (toString id ++ " " ++ u.name)
, ul [] <|
List.map
(\p ->
li []
[ text p.body
, ul [] <|
List.map
(\c ->
li [] [ text c.body ]
)
p.comments
]
)
u.posts
]
)
(toList users)
]
Nothing ->
div []
[ text "Waiting..."
, div [] [ text (toString model) ]
]
-- COMBINING THE VALUE
combine : List JsonUser -> List JsonPost -> List JsonComment -> Dict Int User
combine jUsers jPosts jComments =
List.map
(\u ->
( u.id
, { name = u.name
, username = u.username
, posts =
List.filterMap
(\p ->
if p.userId == u.id then
Just (combinePost p jComments)
else
Nothing
)
jPosts
}
)
)
jUsers
|> Dict.fromList
combinePost : JsonPost -> List JsonComment -> Post
combinePost jPost allComments =
{ body = jPost.body
, comments =
List.filterMap
(\c ->
if c.postId == jPost.id then
Just { body = c.body }
else
Nothing
)
allComments
}
module ZZZFetchJSON exposing (..)
-- This is just for fetching and decoding some related JSON data
import Json.Decode as Json
import Json.Decode exposing ((:=))
usersUrl =
"https://jsonplaceholder.typicode.com/users"
postsUrl =
"https://jsonplaceholder.typicode.com/posts"
commentsUrl =
"https://jsonplaceholder.typicode.com/comments"
type alias JsonUser =
{ id : Int, name : String, username : String }
type alias JsonPost =
{ id : Int, userId : Int, body : String }
type alias JsonComment =
{ id : Int, postId : Int, body : String }
userDecoder : Json.Decoder JsonUser
userDecoder =
Json.object3 JsonUser
("id" := Json.int)
("name" := Json.string)
("username" := Json.string)
postDecoder : Json.Decoder JsonPost
postDecoder =
Json.object3 JsonPost
("id" := Json.int)
("userId" := Json.int)
("body" := Json.string)
commentDecoder : Json.Decoder JsonComment
commentDecoder =
Json.object3 JsonComment
("id" := Json.int)
("postId" := Json.int)
("body" := Json.string)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment