dongliao1860 2016-07-02 16:46
浏览 60
已采纳

Go中的time.Sleep和服务器发送事件-意外行为

I am trying to learn to use server sent events (SSE) with Go. The following is the behavior that I do not understand.

What I expect (and want to implement): one message will be sent after every second; this will happen five times, and then the connection will be closed.

What actually happens: the server waits for about 5 seconds and then sends all messages at once and then the connection is closed.

Would appreciate if you can help me understand why this is happening. It is not clear to me where I am going wrong with how I am thinking about this. Every time the loop starts, it should send a message, sleep and then start a new iteration.

Thank you.

Relevant code on server

func realTimeHandler(w http.ResponseWriter, req *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")

    i := 0
    var msg string
    for {
        msg = fmt.Sprintf("data: Message %d

", i)
        i = i + 1
        w.Write([]byte(msg))
        time.Sleep(time.Second)
        if i > 5 {
            break
        }
    }
    w.Write([]byte("data:close

"))
    return
}

Code on client

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>SSE</title>
</head>
<body>
    <div id="realtime"></div>

    <script type="text/javascript">
        var evtsrc = new EventSource("/realTimeEvts");

        evtsrc.onmessage = function(e) {
            console.log("message received");
            if (e.data == "close") {
                console.log("closing connection!");
                evtsrc.close();
            }
            console.log(e.data);
        };

        evtsrc.onerror = function(e) {
            console.log(evtsrc.readyState);
            console.log("error!");
        };
    </script>
</body>
</html>
  • 写回答

1条回答 默认 最新

  • dsqe46004 2016-07-02 17:05
    关注

    The server buffers the response body. Flush the buffer to fix this issue:

    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    f, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "sse not supported", 400)
        return
    }
    for i := 0; i < 5; i++ {
        fmt.Fprintf(w, "data: Message %d
    
    ", i)
        f.Flush()
        time.Sleep(time.Second)
    }
    w.Write([]byte("data:close
    
    "))
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?