为什么此SSE处理程序会导致客户端连接陷入待处理状态?

问题描述 投票:0回答:1

在此示例中,为https://github.com/kljensen/golang-html5-sse-example/blob/d4eba81ddea2b4191f039adb6929086ca6b39c0f/server.go#L130,您可以在频道上进行阻止。但是,在我的HandleExecute中执行此操作会使浏览器/客户端连接状态保持停留在挂起状态,并且没有任何内容发送到客户端。

[如果我删除了for循环并使用带有默认情况下不回写数据的select语句,则它起作用(execute写入并刷新数据),除了处理程序返回并且客户端每5秒重新连接一次,而不是每隔5秒重新连接一次保持连接。当我这样做时,客户端仅在重新连接间隔上获取流数据。

因此,最终用户会看到持续不到5秒的延迟,具体取决于何时按下HandleExecuteRequestHandleExecute可能已准备好编写,但客户端可能尚未重新连接。我希望这是有道理的。

我如何编写这些处理程序以保持恒定的连接而不是重新连接?

func (s *Server) HandleExecuteRequest(w http.ResponseWriter, r *http.Request) {
    err := r.ParseForm()
    if err != nil {
        log.Printf("Error parsing request: %v", err)
        fmt.Fprintf(w, "Error parsing request: %v", err)
        return
    }

    decoder := schema.NewDecoder()
    var f Form
    err = decoder.Decode(&f, r.PostForm)
    if err != nil {
        log.Printf("Error decoding form: %v", err)
        fmt.Fprintf(w, "Error decoding form: %v", err)
        return
    }

    s.clientMap[r.RemoteAddr] <- buildCommand(&f)
}

func (s *Server) HandleExecute(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    s.addClient(r)

    for {
        cmd := <-s.clientMap[r.RemoteAddr]
        execute(w, cmd)
    }
}

Javascript

var source = new EventSource('<host>/execute');
source.onmessage = function(e) {
document.querySelector("code").innerHTML +="<span class='font-weight-bold' style='white-space: pre-wrap; padding-left: 200px;'>" + e.data + "</span>" + "<br>"
};

如果将HandleExecute更新为以下版本,则会得到一个连续的连接,但是当被击中时,HandleExecuteRequest将停留在挂起状态。在这种情况下,这可能是我如何设置客户端和处理渠道的方法。

func (s *Server) HandleExecute(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    s.addClient(r)

    for {
        select {
        case cmd := <-s.clientMap[r.RemoteAddr]:
            execute(w, cmd)
        default:
            fmt.Fprint(w, ": no data\n\n")
        }
    }
}
javascript go server-sent-events
1个回答
0
投票

我的问题与SSE处理程序的设置无关。我的频道设置不正确,并阻止了连接。

© www.soinside.com 2019 - 2024. All rights reserved.