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] 
> <javascript:>> 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] <javascript:>.
>> 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