0
votes

I am trying to setup a basic stream between my Golang server and VueJS. I followed another post on StackOverflow to get started. However, for some odd reason when I check my console in chrome the output is continuously repeated (0, 1, 2, 3, 4 -short stop- 0, 1, 2, 3, 4 -short stop- etc..).

Here's my code

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>

I'm new to SSE & Vue but I thought the client waits for a response from the server. My expectation is that, once the Gin stream ends, the client just keeps waiting and doesn't do anything until I do EventSource.close(). The output seems like the server sends the response normally but the client keeps making a request once the stream ends? I'm not sure. Can someone point out what I'm doing wrong? Thanks

1

1 Answers

0
votes

You are not wrong, actually. That's the intended function of EventSource api, it always fire the call unless it stopped explicitly. Check 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().

So you need to update when the server has finished to send its data and let the client know if the stream has been stopped. This is the example from your code:

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);
        }
    });