I haven't used an effect manager for this because I haven put in the time
needed to learn how to create effect managers. :)

If what I've shown here can be accomplished with an effect manager then
that's the way it should be done.  :)






On Wed, Jun 1, 2016 at 10:21 AM, James Wilson <[email protected]> wrote:

> Thanks, that looks like basically exactly what I'd have guessed :) It's
> super useful seeing an actual code sample with these ideas in.
>
> One thing I wonder now is; why not use an effect manager for this? It
> basically seems to fit the exact same space (allows you to create a custom
> Req like thing that can be mapped and batched and passed up the component
> hierarchy - except that it's just a Cmd instead and plays nice with other
> Cmds; allows you to maintain and update state (the cache) as you go; allows
> you to "convert" Reqs to tasks to be run - just Cmds again now). In fact,
> effect managers don't really seem to help you do anything other than what's
> described here (plus a subscription side if you want it). Are there any
> cons to using an effect manager here that you have in mind?
>
> On Tuesday, 31 May 2016 20:43:41 UTC+1, Peter Damoc wrote:
>>
>> The updating of the cache sounds to me like this:
>>
>> 1. if we have the info in cache, just supply the info without a HTTP GET
>> 2. if we don't have the info in cache, return a different Msg that
>> encapsulates the msg that requested the original information and the info
>> required for the cache update.
>>
>> Here is a quick update of the code I've previously posted to include this
>> caching mechanism.
>>
>> https://gist.github.com/pdamoc/d492ab58023926cd4d4950f12e5e170d
>>
>>
>>
>>
>> On Tue, May 31, 2016 at 10:05 PM, James Wilson <[email protected]> wrote:
>>
>>> The key part that's not coded in the gist is the use of a cache/global
>>> state object, however I think I  see what you're getting at - pass back up
>>> the chain a Req object, say, and at the top we can turn it into a Cmd
>>> using, say, some top level global state as well as whatever other data we
>>> need. This may lead to a request being made to the server or it may not.
>>>
>>> The other part of the puzzle is actually updating the cache when a
>>> request is made. Req.toCmd for instance could return an updated GlobalState
>>> so that it's able to cache "pending" states on values (so that we can avoid
>>> duplicating requests). To update the cache when the response actually comes
>>> in we could have toCmd return a Cmd.batch of 2 commands, one that will
>>> fail/succeed and send a message to the component that initiated the Req,
>>> and one that will send a message aimed at the top level cache itself.
>>>
>>> Thanks Peter, I'll definitely mull over this!
>>>
>>> On Tuesday, 31 May 2016 19:45:42 UTC+1, Peter Damoc wrote:
>>>>
>>>> ADT in Elm is one of its most powerful weapons.
>>>>
>>>> You could encapsulate your requests in a type and use this type at top
>>>> level to fulfill them.
>>>>
>>>> For example: instead of returning Cmd msg you return some Req msg that
>>>> can be turned into a Cmd msg at top level based on some context
>>>> information.
>>>>
>>>> Here is a gist with a skeleton of how I view this implemented:
>>>> https://gist.github.com/pdamoc/a47090e69b75433efa60fe4f70e6a06a
>>>>
>>>> I've sent the base of the URL as a simple String in `Req.toCmd` but you
>>>> can imagine a more complex type holding all kind of information (e.g.
>>>> cache, auth, etc ) .
>>>> Also, I've kept the type of the Req simple (only saved the rest of the
>>>> URL based on the user and the request) but one could use it to store all
>>>> the info needed when you will turn the Req into a Cmd.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Tue, May 31, 2016 at 7:29 PM, James Wilson <[email protected]> wrote:
>>>>
>>>>> In Elm, each component basically has its own internal state (which is
>>>>> actually all just a slice of one global model). In my app, I also want
>>>>> global state that is independant of any components; for example a
>>>>> clientside cache of various API responses (asset details - there could be
>>>>> many thousands, user authentication status).
>>>>>
>>>>> I want any component to be able to call methods that make use of this
>>>>> global state. For example, a method to obtain details for items in the
>>>>> current view might first look at the global state to see if these items 
>>>>> are
>>>>> cached. If they arent, the call would provide a Cmd to be issued that gets
>>>>> the items (and puts them in the cache), while simultaneously updating the
>>>>> state to indicate that they are being loaded (so that the same request
>>>>> again from another component doesnt trigger another call to the backend).
>>>>> If they are cached, they can be easily returned from there. A first shot 
>>>>> at
>>>>> a signature might look something like:
>>>>>
>>>>> getItem : GlobalState -> ID -> Tag -> (GlobalState, Cmd msg)
>>>>>
>>>>>
>>>>>
>>>>> However we could partially apply functions that exist on some
>>>>> globalState instantiation to hdie the initial state being passed in and 
>>>>> end
>>>>> up with:
>>>>>
>>>>> state.items.getItem : ID -> Tag -> (GlobalState, Cmd msg)
>>>>>
>>>>>
>>>>>
>>>>> The downside of this approach is that I have to thread this state
>>>>> through multiple calls that might make use of it, and thread it back up
>>>>> explicitly through the update functions to get it back to the top. At the
>>>>> top we'd then have something like (excuse any mistakes!):
>>>>>
>>>>> update msg model = case msg of
>>>>>    SubMsg m ->
>>>>>      let (newSubModel, subCmds, newGlobalState) = SubComponent.update
>>>>> m model.subModel
>>>>>      in ({ model | state = newGlobalState, subModel = newSubModel},
>>>>> Sub.map SubMsg subCmds)
>>>>>    ...
>>>>>
>>>>>
>>>>> An alternative approach is to hold this global state in an effect
>>>>> manager, and so in the app you'd end up using the Cmd/Sub mechanism to ask
>>>>> for things from the state and internally initiate API requests to update
>>>>> the state as necessary. We'd end up with an API more like:
>>>>>
>>>>> getItem : ID -> Tag -> Cmd msg
>>>>>
>>>>>
>>>>> or
>>>>>
>>>>> state.items.getItem : ID -> Tag -> Cmd msg
>>>>>
>>>>>
>>>>> where the returned Cmd would either lead to an item being sent to the
>>>>> component immediately via a cache (where Tag is a Msg type the component
>>>>> knows about) or after it was obtained via some backend. This would make 
>>>>> all
>>>>> retrieving of state async but seems to simplify the interface (perhaps at
>>>>> the cost of more complexity in implementing the effect manager).
>>>>>
>>>>> Which approach do people think is best for working with global state
>>>>> (neither is an option if you have a better way!)? Do you get away with not
>>>>> needing this kind of thing (and if so, how)? I'd love to hear back,
>>>>> especially from those that have had experience building larger apps in 
>>>>> Elm!
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "Elm Discuss" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to [email protected].
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> There is NO FATE, we are the creators.
>>>> blog: http://damoc.ro/
>>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Elm Discuss" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>
>>
>> --
>> There is NO FATE, we are the creators.
>> blog: http://damoc.ro/
>>
> --
> You received this message because you are subscribed to the Google Groups
> "Elm Discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>



-- 
There is NO FATE, we are the creators.
blog: http://damoc.ro/

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to