Integrate Http requests with the rest of the updates

后端 未结 1 1234
广开言路
广开言路 2021-01-22 06:57

I am making a simple Elm application with the following model:

type alias Model =
    { num : Float
    , str : String
    , list : List Float
    , serverRespon         


        
相关标签:
1条回答
  • 2021-01-22 07:27

    Intro

    This is currently a little harder to do than it should be. The next Elm release (0.15) should take care of the awkwardness with a new language feature and a revamp of the Http and Websocket libraries among other things.

    The basic problem is a cyclic dependency in your signals. You want to create HTTP requests based on your program state ("the current model") and update the program state based on the HTTP responses. This should totally be possible because there is this asynchronous HTTP handling in between, not some senseless recursive definition that cannot be.

    Workaround (hack): JavaScript echo service

    But since we're still at Elm 0.14, I'll show you a workaround. Please note that this is a dangerous hack! I'll base this code on the definitions you gave and only repeat names where I redefine. The comments explain what's happening.

    Elm code

    -- These are the Http response strings, but coming from JavaScript through a port
    port asyncResponses : Signal String
    
    responseActions : Signal Action
    responseActions = responseToAction <~ asyncResponses
    
    -- The order of these two parameters of merge may matter. Check which should take precedence. 
    input : Signal Action
    input = Signal.merge responseActions (Signal.subscribe updates)
    
    -- note the redefinition:
    main : Signal Html
    main = Signal.foldp update initialModel input
    
    -- These are the same Http response strings, but we're sending them out so JavaScript can listen to them. 
    port responses : Signal String
    port responses = Http.send requests |> Signal.keepIf isSuccess (Success "") |> Signal.map (\Success s -> s)
    
    isSuccess response = case response of
      Success _ -> True
      _ -> False
    

    JS code

    You should have an HTML file in which you kick off the Elm program with Elm.fullscreen or Elm.embed. I'm going to presume you use the fullscreen version:

    // Catching the returned object from Elm.fullscreen:
    var program = Elm.fullscreen(Elm.Main, {asyncResponses : ""})
    // JS Echo Service:
    program.ports.responses.subscribe(function(s) {
      program.ports.asyncResponses.send(s);
    })
    

    Dangers

    I hope it's obvious that jumping through these hoops is annoying and messy and not normal Elm code style. And I hope that's enough to discourage people from abusing this. And I repeat, this is going to be fixed in a nicer way in the upcoming Elm 0.15.

    The dangers of this method are that you send more events to the Elm program than you get in JavaScript. It may be non-obvious that this can happen to a such a simple piece of JS that echoes what it gets. But the problem may come from your Elm program. If your Elm program sends an Http response string out of the port for every string it gets through the other port, and also (for example) repeats that response when some other input changes your model, then you start to accumulate events that get echoed. Normally Elm can be clever about event synchronisation but with ports all bets are off and you can overtax the system with accumulating events that make the program lag and the browser hog memory. So please be careful, and don't advertise this trick as a good thing. It's only a stopgap.

    Resources

    1. Documentation of Ports
    2. Example project for using ports
    3. A short mailing list discussion about the same problem and solution.
    4. An example Elm game from the ludum dare mini, which uses the same technique for playing and stopping audio. I explained this solution to one of the creators on the #elm IRC channel. Note they had to use a dropRepeats on the outgoing port to keep the echoed events from JavaScript from piling up.
    5. Tentative new APIs for these kind of things in Elm 0.15.
    0 讨论(0)
提交回复
热议问题