服务器发送事件意外行为

Server Sent Event unexpected behavior

我正在尝试在我的 Golang 服务器和 VueJS 之间设置一个基本流。我在 Whosebug 上关注了另一个 post 开始。但是,由于某些奇怪的原因,当我在 chrome 中检查我的控制台时,输出不断重复(0、1、2、3、4 -short stop- 0、1、2、3、4 -short stop- etc ..).

这是我的代码

main.go

  package main

  import (
    "io"
    "time"

    "github.com/gin-contrib/static"
    "github.com/gin-gonic/gin"
  )
  
  func main() {
        r := gin.Default()
        r.GET("/stream", func(c *gin.Context) {
            chanStream := make(chan int, 2)
            go func() {
                defer close(chanStream)
                for i := 0; i < 5; i++ {
                    chanStream <- i
                    time.Sleep(time.Second * 1)
                }
            }()
            c.Stream(func(w io.Writer) bool {
                if msg, ok := <-chanStream; ok {
                    c.SSEvent("message", msg)
                    return true
                }
                return false
            })
        })
        r.StaticFile("/", "./public.html") 
        r.Use(static.Serve("/", static.LocalFile("./public.html", true)))
        r.Run()
  }

public.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>
var stream = new EventSource("/stream");
stream.addEventListener("message", function(e){
    console.log(e.data);
});
</script>    
</body>
</html>

我是 SSE 和 Vue 的新手,但我认为客户端正在等待服务器的响应。我的期望是,一旦 Gin 流结束,客户端就一直等待并且在我执行 EventSource.close() 之前不做任何事情。输出似乎服务器正常发送响应,但客户端在流结束后继续发出请求?我不确定。有人可以指出我做错了什么吗?谢谢

其实你没有看错。这是 EventSource api 的预期功能,它总是触发调用,除非它明确停止。检查 EventSource API

The EventSource interface is web content's interface to server-sent events. An EventSource instance opens a persistent connection to an HTTP server, which sends events in text/event-stream format. The connection remains open until closed by calling EventSource.close().

因此您需要在服务器完成发送数据时进行更新,并让客户端知道流是否已停止。这是您代码中的示例:

main.go

        go func() {
            defer close(chanStream)
            for i := 0; i < 5; i++ {
                chanStream <- i
                time.Sleep(time.Second * 1)
            }
        }()
        c.Stream(func(w io.Writer) bool {
            if msg, ok := <-chanStream; ok {
                if msg < 4 {
                    c.SSEvent("message", msg)
                } else {
                    c.SSEvent("message", "STOPPED")
                }
                return true
            }
            return false
        })

public.html

    stream.addEventListener("message", function(e){
        if (e.data === "STOPPED") {
            console.log("STOP");
            stream.close();
        } else {
            console.log(e.data);
        }
    });