How to do two independent actions within one function?

How can I do two independent actions inside one function in Elm? Is there some kind of pattern or explicit function?

Generally speaking, I am not sure how to implement ajax data loading inside Elm Architecture .

For example, I would like to do Http.get

and return a modified argument function like this

fetchCustomers model =
  Http.get parseCustomers "/customers" `andThen` setCustomers
  { model | fetchingCustomers <- True }

      

+3


source to share


1 answer


TL; DR

You do this by returning both in a tuple. Then you will strip the signal from your update to foldp

, put a portion of the model into a view function, and put tasks on a port to be executed. This is mentioned in the "Architecture" column at the end of "One Last Pattern" .

Longer answer

Since you are referring to Elm Architecture, let me also refer to this, but in particular the last part: One final pattern .

What you want to do here is the "update" part of your program, where you not only update your model but do something else on the side. So you're not just returning a new model, but an additional thing you want to do (in this case, an Http request):



fetchCustomers model =
  ( { model | fetchingCustomers <- True }
  , Http.get parseCustomers "/customers" `andThen` setCustomers
  )

      

Instead of using a StartApp like an architecture page, you can insert a start

function
from a package. You now have access to the mailbox where the activity is taking place, so you can pipe it to your update so you can post the results Http

there too. And you can split the tuple you return from the update function to actually do the tasks:

start app =
  let
    actions =
      Signal.mailbox Nothing

    address =
      Signal.forwardTo actions.address Just

    model =
      Signal.foldp
        (\(Just action) (model,_) -> app.update actions action model)
        -- ignore task: ^     ^^^              ^^^^^^^^:add mailbox
        app.model
        actions.signal
  in
    (Signal.map (fst >> app.view address) model, Signal.map snd model)
--  ^           ^^^^^^^     :split model:      ^^^^^^^^^^^^^^^^^^^^^^^


fetchCustomers actions model =
  ( { model | fetchingCustomers <- True }
  , Http.get parseCustomers "/customers"
    `andThen` (SetCustomers >> Signal.send actions.address)
  -- use mailbox to send Http results as an input action again
  )

-- larger update function you probably have
update actions action model = case action of
  -- ...
  SetCustomers cust -> setCustomers cust
  -- ...
  -- fetchCustomers actions model

(output, tasks) = start { model: model, view: view, update: update }

-- task execution:
port httpGets = tasks

-- output your view
main = output

      

You can find more examples of execution Http

on the website under "Tasks".

+3


source







All Articles