在本例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")
}
}
}
发布于 2020-02-08 02:38:42
我的问题与SSE处理程序的设置无关。我的频道设置不正确,并且阻塞了连接。
https://stackoverflow.com/questions/60106498
复制相似问题