将Http请求与其余更新集成 [英] Integrate Http requests with the rest of the updates

查看:65
本文介绍了将Http请求与其余更新集成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下模型制作一个简单的Elm应用程序:

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

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

我遵循Todo-MVC示例,并且具有类似的体系结构:

I am following the Todo-MVC example and I have a similar architecture:

type Action
    = NoOp
    | ChangeNum String
    | ChangeStr String
    ...

view : Model -> Html
view model =
    ...

update : Action -> Model -> Model
update action model =
    case action of
    ...

main : Signal Html
main = Signal.map view model

model : Signal Model
model = Signal.foldp update initialModel (Signal.subscribe updates)

initialModel : Model
initialModel =
    ...

updates : Signal.Channel Action
updates = Signal.channel NoOp



<我正在尝试添加一个将模型发布到某个页面的按钮,并返回带有服务器响应的model.serverResponse更新。但是我完全迷住了。

I am trying to add a button that will POST the model to some page and in return update model.serverResponse with the server's response. But I am completely stumped.

有人可以帮我填补以下代码的空白吗: http://pastebin.com/1irNqh3S

Can someone help me fill the gap in this code: http://pastebin.com/1irNqh3S

推荐答案

简介



目前这比应该做的要难一些。 Elm的下一个发行版本(0.15)应该具有新语言功能并改进 Http Websocket 库等。

基本问题是信号中的循环依赖关系。您要基于程序状态(当前模型)创建HTTP请求,并根据HTTP响应更新程序状态。这应该完全有可能,因为在两者之间存在异步HTTP处理,而不是不可能的一些毫无意义的递归定义。

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.

但是由于我们仍然处于Elm 0.14,我会告诉您一种解决方法。 请注意,这是危险黑客!!我将根据您提供的定义将此代码作为基础,并且仅在我重新定义的地方重复这些名称。这些评论说明了正在发生的事情。

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.

-- 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代码



您应该拥有一个HTML文件,您可以使用 Elm.fullscreen Elm.embed 启动Elm程序。我假设您使用的是全屏版本:

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);
})



危险



我希望很明显,跳过这些箍很烦人且凌乱,而不是正常的Elm代码风格。我希望这足以阻止人们滥用它。我重复一遍,在即将发布的Elm 0.15中将以更好的方式解决此问题。

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.

此方法的危险在于,向Elm程序发送的事件比在JavaScript中发送的事件多。看起来如此简单的JS可能会发生这种情况,但这种情况并不明显,它会回显它所得到的。但是问题可能出在您的Elm程序上。如果您的Elm程序从端口通过端口发送的每个字符串都从端口发送Http响应字符串,并且(例如)在其他一些输入更改模型时也重复该响应,那么您将开始积累被回显的事件。通常,Elm对于事件同步可能比较聪明,但是在端口关闭的情况下,所有选项都关闭了,并且您可以通过累积事件来加重系统负担,这些事件会使程序滞后,并占用浏览器的内存。因此,请小心,不要将此技巧宣传为好东西。这只是权宜之计。

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.


  1. 端口

  2. 示例项目使用端口

  3. 简短的关于相同问题和解决方案的邮件列表讨论

  4. 一个示例榆木游戏来自ludum dare mini,它使用相同的技术播放和停止音频。我在 #elm IRC频道上向一位创建者介绍了此解决方案。请注意,他们必须在传出端口上使用 dropRepeats 来防止来自JavaScript的回显事件堆积。

  5. 暂定的新API 对于Elm 0.15中的此类情况。

  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.

这篇关于将Http请求与其余更新集成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆