在此示例中,为https://github.com/kljensen/golang-html5-sse-example/blob/d4eba81ddea2b4191f039adb6929086ca6b39c0f/server.go#L130,您可以在频道上进行阻止。但是,在我的HandleExecute
中执行此操作会使浏览器/客户端连接状态保持停留在挂起状态,并且没有任何内容发送到客户端。
[如果我删除了for循环并使用带有默认情况下不回写数据的select语句,则它起作用(execute
写入并刷新数据),除了处理程序返回并且客户端每5秒重新连接一次,而不是每隔5秒重新连接一次保持连接。当我这样做时,客户端仅在重新连接间隔上获取流数据。
因此,最终用户会看到持续不到5秒的延迟,具体取决于何时按下HandleExecuteRequest
。 HandleExecute
可能已准备好编写,但客户端可能尚未重新连接。我希望这是有道理的。
我如何编写这些处理程序以保持恒定的连接而不是重新连接?
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")
}
}
}
我的问题与SSE处理程序的设置无关。我的频道设置不正确,并阻止了连接。