"input is undefined" 在 Elm 中使用 WebSockets 时出错

"input is undefined" error when using WebSockets in Elm

我正在尝试在 Elm 中使用 WebSockets 设置一个简单示例,但我一直收到 运行 时间错误 "input is undefined"。控制台在我的 elm 文件中没有给我任何行号或类似的东西。

我试图在一个大型项目中使用 WebSockets,但我一直收到错误 "a is undefined",所以我决定制作这个小示例来尝试找出问题所在。

我写了一些代码来接收包含来自 websocket 的数字的消息。它递增数字,然后通过网络套接字将新数字发回。服务器做同样的事情,将递增1的数字发送回客户端。

这里是榆树代码:

import Graphics.Element (Element)
import Signal
import Signal (Signal)
import Text
import Window
import WebSocket
import String

type State = Num Int
           | StateErr String

input : Signal String
input =
    WebSocket.connect "ws://localhost:4567/test" sendToServer

sendToServer : Signal String
sendToServer =
    Signal.dropRepeats
        (Signal.dropIf (\str -> str == "") "" (Signal.map formatReply state))

formatReply : State -> String
formatReply state =
    case state of
        Num n -> toString n
        StateErr str -> ""


stepState : String -> State -> State
stepState str state =
    case (String.toInt str) of
        Ok n -> Num (n + 1)
        Err str -> StateErr str


display : (Int,Int) -> State -> Element
display (w,h) state = Text.asText state


state : Signal State
state =
    Signal.foldp stepState (Num 0) input


main : Signal Element
main =
    Signal.map2 display Window.dimensions state

我测试了服务器端,它工作正常,所以我绝对不认为是服务器导致了问题。

当我在 Firefox 中尝试代码时,我得到 "input is undefined"。当我在 Chrome 中 运行 时,我得到 "Cannot read property 'kids' of undefined"。 在 Chrome 中,查看堆栈跟踪似乎是当代码转到 运行 时, 输入未定义 。这是 WebSocket 库的错误吗?

我对使用 Elm 很陌生,所以我很感激 help/advice 使用 websockets。

我了解到造成我麻烦的原因是,截至目前,elm 中的 WebSockets 库尚未完全实现。我还了解到我可以使用端口实现我的目标,然后在 javascript.

中实现 websocket

我将以下 javascript 添加到我的 html 文件中:

var game = Elm.fullscreen(Elm.SlimeWarz, {rawServerInput: ""});
var socket = new WebSocket("ws://localhost:4567");

socket.onopen = function(){
  console.log("Socket has been opened.");
}

socket.onmessage = function(msg){
  game.ports.rawServerInput.send(msg.data);
}

game.ports.sendToServer.subscribe(sendOverWebsocket);

function sendOverWebsocket(str) {
  socket.send(str);
}

然后在 elm 中,我可以使用名为 sendtoServer 的移植信号发送数据

port sendToServer : Signal String

并且我可以通过移植信号 rawServerInput 查看我接收到的所有数据

port rawServerInput : Signal String

回答

我将使用 . I think 的一部分来使用端口,并且 JavaScript 中的 websocket 部分比我在那个答案中描述的 hack 更好,但是你可能还想看看。一旦 Elm 0.15 发布,这个问题应该完全消失,因为语言特性和 Websocket 的改造(顺便说一句,Http 也进行了改造)。

上下文:错误原因

您收到运行时错误的原因是 compiler bug。编译器仅在递归函数上生成正确的代码,同时它接受 any 递归值。请注意,您的 input 取决于 sendToServersendToserver 取决于 statesContext: tate 取决于 input

上下文:代码架构

这类循环信号通常是程序架构不佳的标志。您可以找到有关该主题的更多信息 here但是您的体系结构并没有错。问题在于 Websocket 库没有引导您朝着正确的方向前进。