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.
