刷新浏览器

时间:2016-12-01 04:48:24

标签: javascript go websocket

我的Websocket服务器用go编写,包github.com/gorilla/websocket

服务器有2个用于接收和发送消息的循环。 http处理程序的实现如下所示:

upgrader, errChan := websocket.Upgrader{}, make(chan error)

ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
}

// incoming messages

go func() { 
    for {
        message := Message{}
        if err := ws.ReadJSON(&message); err != nil {
            errChan <- err
        }
        handleMessage(message)
    }
}()

// outgoing messages 

go func() { 
    for {
        message := <-global.outgoingMessage
        if err = ws.WriteMessage(websocket.TextMessage, message); err != nil {
            errChan <- err
        }
    }
}()

err = <- errChan
ws.Close()

客户端应用程序使用React,应用程序将消息用作状态。启动应用程序时,将建立websocket连接,并且onopen回调将触发对初始数据的请求。响应由onmessage捕获,该消息用于app状态。实现如下所示:

var ws = new WebSocket("ws://localhost:8080/app")

ws.onerror = function(err) {
    alert(err)
}
ws.onmessage = function(m) {
    var state = JSON.parse(m.data)
    global.app.setState(state) 
}
ws.onopen = function() { 
    ws.send('{"type":"init"}')
}

通过此设置,我注意到的是我第一次启动应用程序并浏览页面时一切正常。刷新浏览器后,它就不再有效了。我可以拨打ws.send('{"type":"init"}')并查看服务器发送的响应,但onmessage回调不会被解雇。在多次尝试调用ws.send('{"type":"init"}')之后,onmessage最终会被调用一次并且应用程序状态被加载。如果我杀死并重新启动应用程序,则会发生相同的行为。

思想?

1 个答案:

答案 0 :(得分:0)

看起来所有输出goroutine都从单个通道global.outgoingMessage接收,并且没有足够的消息发送到此通道以满足所有正在运行的输出goroutine。

如果应用程序的目的是向所有连接的客户端广播,那么我建议遵循Gorilla chat example中的集线器模式。

除此之外:应用程序泄漏了goroutines。有关说明,请参阅this question