Primo: la funzione decoder
è leggermente disattivata. Non v'è alcun intermedio "attributi" oggetto, in modo da poter cambiare a questo:
decoder : Decoder Job
decoder =
Decode.object3 Job
("task" := Decode.string)
("who" := Decode.string)
("place" := Decode.string)
Lei ha ragione che è necessario il pacchetto elm-http. Utilizzando questo, è possibile creare un'attività Http.get
che associa il risultato a un'azione.
Come esempio di base, facciamo un pulsante che tira giù l'elenco dei lavori da un url. Avremo bisogno di un'azione GetJobs
per attivare la richiesta HTTP e un'azione ShowJobs
che verrà attivata quando la richiesta ritorna correttamente.
Supponendo che il nostro tipo di azione si presenta così:
type Action
= NoOp
| GetJobs
| ShowJobs (Maybe Jobs)
Poi possiamo creare una funzione getJobs
che costruisce un compito che può essere eseguito. Per questo semplice esempio, possiamo usare Task.toMaybe
per sopprimere eventuali errori di decodifica HTTP o JSON.
getJobs : Effects Action
getJobs =
Http.get decoderColl jobsUrl
|> Task.toMaybe
|> Task.map ShowJobs
|> Effects.task
Al fine di incollare tutto insieme, useremo StartApp poiché ci consente di utilizzare le attività e gli effetti. Ecco un esempio funzionante che è possibile creare in locale, assumendo che jobs.json esista nella stessa directory.
import Http
import StartApp
import Effects exposing (Effects,Never)
import Task
import Html exposing (..)
import Html.Events exposing (..)
import Json.Decode as Decode exposing (Decoder, (:=))
jobsUrl = "./jobs.json"
-- StartApp plumbing
app =
StartApp.start { init = init, view = view, update = update, inputs = [] }
main =
app.html
port tasks : Signal (Task.Task Never())
port tasks =
app.tasks
type Action
= NoOp
| GetJobs
| ShowJobs (Maybe Jobs)
type alias Model =
{ jobs : Maybe Jobs }
init =
({ jobs = Nothing }, Effects.none)
update action model =
case action of
NoOp ->
(model, Effects.none)
GetJobs ->
({ model | jobs = Nothing }, getJobs)
ShowJobs maybeJobs ->
({ model | jobs = maybeJobs }, Effects.none)
view address model =
div []
[ button [ onClick address GetJobs ] [ text "Click to get jobs!" ]
, viewJobs model.jobs
]
viewJobs maybeJobs =
let
viewJob job =
li [] [ text ("Task: " ++ job.task ++ "; Who: " ++ job.who ++ "; Place: " ++ job.place) ]
in
case maybeJobs of
Nothing ->
div [] [ text "No jobs to display. Try clicking the button" ]
Just jobs ->
ul [] (List.map viewJob jobs)
-- This is the key to map the result of the HTTP GET to an Action
-- Note: Task.toMaybe swallows any HTTP or JSON decoding errors
getJobs : Effects Action
getJobs =
Http.get decoderColl jobsUrl
|> Task.toMaybe
|> Task.map ShowJobs
|> Effects.task
-- An alternative to Task.toMaybe which dumps error information to the console log
toMaybeWithLogging : Task.Task x a -> Task.Task y (Maybe a)
toMaybeWithLogging task =
Task.map Just task `Task.onError` (\msg -> Debug.log (toString msg) (Task.succeed Nothing))
-- The Job type aliases from the question
type alias Job = {
task : String
, who : String
, place: String
}
type alias Jobs = List Job
-- The updated Job decoder
decoder : Decoder Job
decoder =
Decode.object3 Job
("task" := Decode.string)
("who" := Decode.string)
("place" := Decode.string)
decoderColl : Decoder Jobs
decoderColl =
Decode.object1 identity
("jobs" := Decode.list decoder)
Per qualche motivo, quando provo a compilare il codice, la memoria è esaurita, non l'ho mai avuta prima. – Stanko
Trovato il problema, avevo bisogno di cambiare '({model | jobs = Nothing}, getJobs)' a '({model | jobs <- Nothing}, getJobs)'. Qual è la differenza tra '=' e '<-'? – Stanko
'<-' è stato modificato in' = 'in quel contesto recentemente nella versione 0.16. Sembra che tu abbia solo bisogno dell'ultima versione di elm –