=sse: events
This commit is contained in:
parent
f4462e5df1
commit
1f96ed0930
28 changed files with 209 additions and 138 deletions
1
sse/be/.gitignore
vendored
Normal file
1
sse/be/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
static
|
BIN
sse/be/be
BIN
sse/be/be
Binary file not shown.
255
sse/be/main.go
255
sse/be/main.go
|
@ -1,9 +1,12 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -15,14 +18,20 @@ type Message struct {
|
|||
Id string `json:"id"`
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
Message chan Message
|
||||
NewClient chan chan Message
|
||||
ClosedClient chan chan Message
|
||||
TotalClients map[chan Message]bool
|
||||
type ClientChan chan Message
|
||||
|
||||
type Client struct {
|
||||
Id string `json:"id"`
|
||||
Ip string `json:"ip"`
|
||||
Chan ClientChan `json:"chan"`
|
||||
Events []string `json:"events"`
|
||||
}
|
||||
|
||||
type ClientChan chan Message
|
||||
type Event struct {
|
||||
Clients []Client `json:"clients"`
|
||||
Id int `json:"id"`
|
||||
Events []string `json:"events"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
|
@ -32,10 +41,12 @@ func main() {
|
|||
event := NewServer()
|
||||
|
||||
api := r.Group("/api")
|
||||
api.GET("/sse", HeadersMiddleware(), event.serveHTTP(), event.retvalSSE())
|
||||
api.GET("/msg", event.SendNewMsg())
|
||||
api.GET("/ping", event.SendPing())
|
||||
api.GET("/pong", event.SendPong())
|
||||
// api.GET("/sse", HeadersMiddleware(), event.serveHTTP(), event.retvalSSE())
|
||||
api.GET("/sse", HeadersMiddleware(), event.Stream)
|
||||
api.GET("/msg", event.SendMsg)
|
||||
api.GET("/message", event.SendMessage)
|
||||
api.GET("/ping", event.SendPing)
|
||||
api.GET("/pong", event.SendPong)
|
||||
|
||||
sse := r.Group("/sse")
|
||||
sse.Static("/", "./static/sse")
|
||||
|
@ -56,16 +67,16 @@ func main() {
|
|||
}
|
||||
|
||||
func NewServer() *Event {
|
||||
event := &Event{
|
||||
Message: make(chan Message),
|
||||
NewClient: make(chan chan string),
|
||||
ClosedClient: make(chan chan string),
|
||||
TotalClients: make(map[chan string]bool),
|
||||
return &Event{
|
||||
Clients: []Client{},
|
||||
Id: 0,
|
||||
Events: []string{
|
||||
"ping",
|
||||
"pong",
|
||||
"msg",
|
||||
"message",
|
||||
},
|
||||
}
|
||||
|
||||
go event.Broadcast()
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
func HeadersMiddleware() gin.HandlerFunc {
|
||||
|
@ -79,98 +90,146 @@ func HeadersMiddleware() gin.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func (e *Event) serveHTTP() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// Initialize client channel
|
||||
clientChan := make(ClientChan)
|
||||
func (e *Event) Stream(c *gin.Context) {
|
||||
client := &Client{
|
||||
Ip: c.ClientIP(),
|
||||
Chan: make(ClientChan),
|
||||
Events: c.QueryArray("events"),
|
||||
}
|
||||
|
||||
// Send new connection to event server
|
||||
e.NewClient <- clientChan
|
||||
client.Id = Id(client.Ip, client.Events, 8)
|
||||
|
||||
defer func() {
|
||||
// Send closed connection to event server
|
||||
e.ClosedClient <- clientChan
|
||||
}()
|
||||
log.Printf("Client: %+v", client)
|
||||
|
||||
c.Set("clientChan", clientChan)
|
||||
e.Clients = append(e.Clients, *client)
|
||||
|
||||
c.Next()
|
||||
defer func() {
|
||||
e.Clients = remove(e.Clients, client)
|
||||
close(client.Chan)
|
||||
log.Printf("Client %s disconnected - tot: %d", client.Ip, len(e.Clients))
|
||||
}()
|
||||
|
||||
log.Printf("Client %s connected - tot: %d", client.Ip, len(e.Clients))
|
||||
|
||||
c.Stream(func(w io.Writer) bool {
|
||||
msg, ok := <-client.Chan
|
||||
if ok {
|
||||
c.SSEvent(msg.Event, msg)
|
||||
}
|
||||
return ok
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Event) Send(msg Message) {
|
||||
e.Id++
|
||||
msg.Id = strconv.Itoa(e.Id)
|
||||
for _, client := range e.Clients {
|
||||
client.Chan <- msg
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Event) retvalSSE() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
v, ok := c.Get("clientChan")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
clientChan, ok := v.(ClientChan)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.Stream(func(w io.Writer) bool {
|
||||
msg, ok := <-clientChan
|
||||
if ok {
|
||||
c.SSEvent("message", msg)
|
||||
}
|
||||
return ok
|
||||
})
|
||||
}
|
||||
func (e *Event) SendMessage(c *gin.Context) {
|
||||
e.Send(Message{
|
||||
Event: "message",
|
||||
Data: "Ciao",
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Event) Broadcast() {
|
||||
id := 0
|
||||
for {
|
||||
select {
|
||||
case client := <-e.NewClient:
|
||||
e.TotalClients[client] = true
|
||||
case client := <-e.ClosedClient:
|
||||
delete(e.TotalClients, client)
|
||||
close(client)
|
||||
case message := <-e.Message:
|
||||
id++
|
||||
message.Id = strconv.Itoa(id)
|
||||
for client := range e.TotalClients {
|
||||
// msg, _ := json.Marshal(message)
|
||||
// client <- string(msg)
|
||||
client <- message
|
||||
}
|
||||
func (e *Event) SendMsg(c *gin.Context) {
|
||||
e.Send(Message{
|
||||
Event: "msg",
|
||||
Data: "hello",
|
||||
})
|
||||
}
|
||||
|
||||
func (e *Event) SendPing(c *gin.Context) {
|
||||
e.Send(Message{
|
||||
Event: "ping",
|
||||
Data: "Ping",
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (e *Event) SendPong(c *gin.Context) {
|
||||
e.Send(Message{
|
||||
Event: "pong",
|
||||
Data: "Pong",
|
||||
})
|
||||
}
|
||||
|
||||
func remove(slice []Client, s *Client) []Client {
|
||||
for i, v := range slice {
|
||||
if v.Id == s.Id {
|
||||
return append(slice[:i], slice[i+1:]...)
|
||||
}
|
||||
}
|
||||
return slice
|
||||
}
|
||||
|
||||
func (e *Event) SendNewMsg() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
e.SendMsg(Message{
|
||||
Event: "message",
|
||||
Data: "hello",
|
||||
Id: "1",
|
||||
})
|
||||
}
|
||||
func Id(ip string, events []string, len int) string {
|
||||
str := ip + strings.Join(events, "|")
|
||||
id := sha256.Sum256([]byte(str))
|
||||
|
||||
return fmt.Sprintf("%X", id)[0:len]
|
||||
}
|
||||
|
||||
func (e *Event) SendPing() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
e.SendMsg(Message{
|
||||
Event: "ping",
|
||||
Data: "hello",
|
||||
Id: "1",
|
||||
})
|
||||
}
|
||||
}
|
||||
// func (e *Event) serveHTTP() gin.HandlerFunc {
|
||||
// return func(c *gin.Context) {
|
||||
// // Initialize client channel
|
||||
// clientChan := make(ClientChan)
|
||||
|
||||
func (e *Event) SendPong() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
e.SendMsg(Message{
|
||||
Event: "pong",
|
||||
Data: "hello",
|
||||
Id: "1",
|
||||
})
|
||||
}
|
||||
}
|
||||
// // Send new connection to event server
|
||||
// e.NewClient <- clientChan
|
||||
|
||||
func (e *Event) SendMsg(msg Message) {
|
||||
e.Message <- msg
|
||||
}
|
||||
// defer func() {
|
||||
// // Send closed connection to event server
|
||||
// e.ClosedClient <- clientChan
|
||||
// }()
|
||||
|
||||
// c.Set("clientChan", clientChan)
|
||||
|
||||
// c.Next()
|
||||
// }
|
||||
// }
|
||||
|
||||
// func (e *Event) retvalSSE() gin.HandlerFunc {
|
||||
// return func(c *gin.Context) {
|
||||
// v, ok := c.Get("clientChan")
|
||||
// if !ok {
|
||||
// return
|
||||
// }
|
||||
|
||||
// clientChan, ok := v.(ClientChan)
|
||||
// if !ok {
|
||||
// return
|
||||
// }
|
||||
|
||||
// c.Stream(func(w io.Writer) bool {
|
||||
// msg, ok := <-clientChan
|
||||
// if ok {
|
||||
// c.SSEvent("message", msg)
|
||||
// }
|
||||
// return ok
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
// func (e *Event) Broadcast() {
|
||||
// id := 0
|
||||
// for {
|
||||
// select {
|
||||
// case client := <-e.NewClient:
|
||||
// e.TotalClients[client] = true
|
||||
// case client := <-e.ClosedClient:
|
||||
// delete(e.TotalClients, client)
|
||||
// close(client)
|
||||
// case message := <-e.Message:
|
||||
// id++
|
||||
// for client := range e.TotalClients {
|
||||
// // msg, _ := json.Marshal(message)
|
||||
// // client <- string(msg)
|
||||
// client <- message
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
import{n as d,s as k}from"./scheduler.k-kUyWhY.js";const u=[];function p(t,e=d){let n;const o=new Set;function a(s){if(k(t,s)&&(t=s,n)){const c=!u.length;for(const i of o)i[1](),u.push(i,t);if(c){for(let i=0;i<u.length;i+=2)u[i][0](u[i+1]);u.length=0}}}function l(s){a(s(t))}function r(s,c=d){const i=[s,c];return o.add(i),o.size===1&&(n=e(a,l)||d),s(t),()=>{o.delete(i),o.size===0&&n&&(n(),n=null)}}return{set:a,update:l,subscribe:r}}const m=globalThis.__sveltekit_1omqn18?.base??"",E=globalThis.__sveltekit_1omqn18?.assets??m,A="1703001309124",I="sveltekit:snapshot",w="sveltekit:scroll",y="sveltekit:states",N="sveltekit:pageurl",U="sveltekit:history",L="sveltekit:navigation",_={tap:1,hover:2,viewport:3,eager:4,off:-1,false:-1},g=location.origin;function O(t){if(t instanceof URL)return t;let e=document.baseURI;if(!e){const n=document.getElementsByTagName("base");e=n.length?n[0].href:document.URL}return new URL(t,e)}function Y(){return{x:pageXOffset,y:pageYOffset}}function f(t,e){return t.getAttribute(`data-sveltekit-${e}`)}const b={..._,"":_.hover};function v(t){let e=t.assignedSlot??t.parentNode;return e?.nodeType===11&&(e=e.host),e}function q(t,e){for(;t&&t!==e;){if(t.nodeName.toUpperCase()==="A"&&t.hasAttribute("href"))return t;t=v(t)}}function x(t,e){let n;try{n=new URL(t instanceof SVGAElement?t.href.baseVal:t.href,document.baseURI)}catch{}const o=t instanceof SVGAElement?t.target.baseVal:t.target,a=!n||!!o||T(n,e)||(t.getAttribute("rel")||"").split(/\s+/).includes("external"),l=n?.origin===g&&t.hasAttribute("download");return{url:n,external:a,target:o,download:l}}function P(t){let e=null,n=null,o=null,a=null,l=null,r=null,s=t;for(;s&&s!==document.documentElement;)o===null&&(o=f(s,"preload-code")),a===null&&(a=f(s,"preload-data")),e===null&&(e=f(s,"keepfocus")),n===null&&(n=f(s,"noscroll")),l===null&&(l=f(s,"reload")),r===null&&(r=f(s,"replacestate")),s=v(s);function c(i){switch(i){case"":case"true":return!0;case"off":case"false":return!1;default:return}}return{preload_code:b[o??"off"],preload_data:b[a??"off"],keepfocus:c(e),noscroll:c(n),reload:c(l),replace_state:c(r)}}function h(t){const e=p(t);let n=!0;function o(){n=!0,e.update(r=>r)}function a(r){n=!1,e.set(r)}function l(r){let s;return e.subscribe(c=>{(s===void 0||n&&c!==s)&&r(s=c)})}return{notify:o,set:a,subscribe:l}}function R(){const{set:t,subscribe:e}=p(!1);let n;async function o(){clearTimeout(n);try{const a=await fetch(`${E}/_app/version.json`,{headers:{pragma:"no-cache","cache-control":"no-cache"}});if(!a.ok)return!1;const r=(await a.json()).version!==A;return r&&(t(!0),clearTimeout(n)),r}catch{return!1}}return{subscribe:e,check:o}}function T(t,e){return t.origin!==g||!t.pathname.startsWith(e)}function V(t){t.client}const G={url:h({}),page:h({}),navigating:p(null),updated:R()};export{U as H,L as N,N as P,w as S,y as a,I as b,P as c,G as d,m as e,q as f,x as g,_ as h,T as i,V as j,g as o,O as r,Y as s};
|
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
import{s as E,n as b,e as x}from"../chunks/scheduler.k-kUyWhY.js";import{S,i as j,g as _,m as f,s as q,h as d,j as g,n as h,f as p,c as y,a as l,x as v,o as $}from"../chunks/index.PctGSwCt.js";import{d as C}from"../chunks/singletons.4aHkxUVP.js";const H=()=>{const s=C;return{page:{subscribe:s.page.subscribe},navigating:{subscribe:s.navigating.subscribe},updated:s.updated}},P={subscribe(s){return H().page.subscribe(s)}};function k(s){let t,r=s[0].status+"",o,n,i,c=s[0].error?.message+"",u;return{c(){t=_("h1"),o=f(r),n=q(),i=_("p"),u=f(c)},l(e){t=d(e,"H1",{});var a=g(t);o=h(a,r),a.forEach(p),n=y(e),i=d(e,"P",{});var m=g(i);u=h(m,c),m.forEach(p)},m(e,a){l(e,t,a),v(t,o),l(e,n,a),l(e,i,a),v(i,u)},p(e,[a]){a&1&&r!==(r=e[0].status+"")&&$(o,r),a&1&&c!==(c=e[0].error?.message+"")&&$(u,c)},i:b,o:b,d(e){e&&(p(t),p(n),p(i))}}}function w(s,t,r){let o;return x(s,P,n=>r(0,o=n)),[o]}let D=class extends S{constructor(t){super(),j(this,t,w,k,E,{})}};export{D as component};
|
Binary file not shown.
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
import{s as N,n as y,r as O,o as D}from"../chunks/scheduler.k-kUyWhY.js";import{S as E,i as T,g as m,m as k,s as x,h as w,j as z,n as B,f as u,c as b,y as C,a as g,x as J,z as h,o as L}from"../chunks/index.PctGSwCt.js";function M(p){let c,s,n,i,o="send Msg",t,l,S="send Ping",d,r,v="send Pong",_,$;return{c(){c=m("h1"),s=k(p[0]),n=x(),i=m("button"),i.textContent=o,t=x(),l=m("button"),l.textContent=S,d=x(),r=m("button"),r.textContent=v},l(e){c=w(e,"H1",{});var a=z(c);s=B(a,p[0]),a.forEach(u),n=b(e),i=w(e,"BUTTON",{"data-svelte-h":!0}),C(i)!=="svelte-1a1zt14"&&(i.textContent=o),t=b(e),l=w(e,"BUTTON",{"data-svelte-h":!0}),C(l)!=="svelte-iklzn2"&&(l.textContent=S),d=b(e),r=w(e,"BUTTON",{"data-svelte-h":!0}),C(r)!=="svelte-1i1hqj6"&&(r.textContent=v)},m(e,a){g(e,c,a),J(c,s),g(e,n,a),g(e,i,a),g(e,t,a),g(e,l,a),g(e,d,a),g(e,r,a),_||($=[h(i,"click",P),h(l,"click",U),h(r,"click",j)],_=!0)},p(e,[a]){a&1&&L(s,e[0])},i:y,o:y,d(e){e&&(u(c),u(n),u(i),u(t),u(l),u(d),u(r)),_=!1,O($)}}}function f(){return new Date(Date.now()).toISOString()}async function P(){await fetch("/api/msg")}async function U(){await fetch("/api/ping")}async function j(){await fetch("/api/pong")}function q(p,c,s){let n;function i(){const o=new EventSource("/api/sse");return console.log("subscribe"),o.onopen=()=>{console.log(`sse open ${f()}`),s(0,n=`sse open ${f()}`)},o.onerror=()=>{console.log(`sse error ${f()}`),o.readyState===EventSource.CONNECTING&&console.log(`sse reconnecting ${f()}`),s(0,n=`sse error ${f()}`)},o.onmessage=t=>{let l=JSON.parse(t.data);console.log(`received: ${JSON.stringify(l)}`),s(0,n=`received: ${JSON.stringify(l)} ${Date.now()}`)},o.addEventListener("ping",t=>{console.log(`ping: ${t.data}`),s(0,n=`ping: ${t.data} ${Date.now()}`)}),o.addEventListener("pong",t=>{console.log(`pong: ${t.data}`),s(0,n=`pong: ${t.data} ${Date.now()}`)}),o.addEventListener("message",t=>{console.log(`message: ${t.data}`),s(0,n=`message: ${t.data} ${Date.now()}`)}),()=>{o.close(),console.log(`sse closing ${Date.now()}`)}}return D(()=>i()),s(0,n=""),[n]}class H extends E{constructor(c){super(),T(this,c,q,M,N,{})}}export{H as component};
|
Binary file not shown.
Binary file not shown.
|
@ -1 +1 @@
|
|||
{"version":"1703001309124"}
|
||||
{"version":"1703070251152"}
|
Binary file not shown.
Binary file not shown.
|
@ -5,17 +5,17 @@
|
|||
<link rel="icon" href="/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<link rel="modulepreload" href="/_app/immutable/entry/start.PsjcEp4p.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/entry/start.tfT6_LLF.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/chunks/scheduler.k-kUyWhY.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/chunks/singletons.4aHkxUVP.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/entry/app.zLHOYlGu.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/chunks/singletons.y0J0ZVZx.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/entry/app.ck5GlgzY.js">
|
||||
<link rel="modulepreload" href="/_app/immutable/chunks/index.PctGSwCt.js">
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">
|
||||
<script>
|
||||
{
|
||||
__sveltekit_1omqn18 = {
|
||||
__sveltekit_lfjj3r = {
|
||||
base: "",
|
||||
env: null
|
||||
};
|
||||
|
@ -23,8 +23,8 @@
|
|||
const element = document.currentScript.parentElement;
|
||||
|
||||
Promise.all([
|
||||
import("/_app/immutable/entry/start.PsjcEp4p.js"),
|
||||
import("/_app/immutable/entry/app.zLHOYlGu.js")
|
||||
import("/_app/immutable/entry/start.tfT6_LLF.js"),
|
||||
import("/_app/immutable/entry/app.ck5GlgzY.js")
|
||||
]).then(([kit, app]) => {
|
||||
kit.start(app, element);
|
||||
});
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -5,17 +5,17 @@
|
|||
<link rel="icon" href="../favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<link rel="modulepreload" href="../_app/immutable/entry/start.PsjcEp4p.js">
|
||||
<link rel="modulepreload" href="../_app/immutable/entry/start.tfT6_LLF.js">
|
||||
<link rel="modulepreload" href="../_app/immutable/chunks/scheduler.k-kUyWhY.js">
|
||||
<link rel="modulepreload" href="../_app/immutable/chunks/singletons.4aHkxUVP.js">
|
||||
<link rel="modulepreload" href="../_app/immutable/entry/app.zLHOYlGu.js">
|
||||
<link rel="modulepreload" href="../_app/immutable/chunks/singletons.y0J0ZVZx.js">
|
||||
<link rel="modulepreload" href="../_app/immutable/entry/app.ck5GlgzY.js">
|
||||
<link rel="modulepreload" href="../_app/immutable/chunks/index.PctGSwCt.js">
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">
|
||||
<script>
|
||||
{
|
||||
__sveltekit_1omqn18 = {
|
||||
__sveltekit_lfjj3r = {
|
||||
base: new URL("..", location).pathname.slice(0, -1),
|
||||
env: null
|
||||
};
|
||||
|
@ -23,8 +23,8 @@
|
|||
const element = document.currentScript.parentElement;
|
||||
|
||||
Promise.all([
|
||||
import("../_app/immutable/entry/start.PsjcEp4p.js"),
|
||||
import("../_app/immutable/entry/app.zLHOYlGu.js")
|
||||
import("../_app/immutable/entry/start.tfT6_LLF.js"),
|
||||
import("../_app/immutable/entry/app.ck5GlgzY.js")
|
||||
]).then(([kit, app]) => {
|
||||
kit.start(app, element);
|
||||
});
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -2,6 +2,9 @@
|
|||
import { onMount } from'svelte';
|
||||
|
||||
$: msg = "";
|
||||
$: jmsg = {};
|
||||
$: dping = "";
|
||||
$: dpong = "";
|
||||
|
||||
function now() {
|
||||
const now = new Date(Date.now());
|
||||
|
@ -22,29 +25,37 @@
|
|||
console.log(`sse error ${now()}`);
|
||||
if (sse.readyState === EventSource.CONNECTING) {
|
||||
console.log(`sse reconnecting ${now()}`);
|
||||
msg = `sse reconnecting ${now()}`;
|
||||
} else {
|
||||
msg = `sse error ${now()}`;
|
||||
}
|
||||
msg = `sse error ${now()}`;
|
||||
};
|
||||
|
||||
sse.onmessage = (e) => {
|
||||
let Msg = JSON.parse(e.data);
|
||||
console.log(`received: ${JSON.stringify(Msg)}`);
|
||||
msg = `received: ${JSON.stringify(Msg)} ${Date.now()}`;
|
||||
msg = `received: ${JSON.stringify(Msg)} ${now()}`;
|
||||
jmsg = Msg;
|
||||
};
|
||||
|
||||
sse.addEventListener('ping', (e) => {
|
||||
console.log(`ping: ${e.data}`);
|
||||
msg = `ping: ${e.data} ${Date.now()}`;
|
||||
let Msg = JSON.parse(e.data);
|
||||
msg = `ping: ${Msg.id} ${Msg.data} ${now()}`;
|
||||
console.log(msg);
|
||||
dping = Msg.id;
|
||||
});
|
||||
|
||||
sse.addEventListener('pong', (e) => {
|
||||
console.log(`pong: ${e.data}`);
|
||||
msg = `pong: ${e.data} ${Date.now()}`;
|
||||
let Msg = JSON.parse(e.data);
|
||||
msg = `pong: ${Msg.id} ${Msg.data} ${now()}`;
|
||||
console.log(msg);
|
||||
dpong = Msg.id;
|
||||
});
|
||||
|
||||
sse.addEventListener('message', (e) => {
|
||||
console.log(`message: ${e.data}`);
|
||||
msg = `message: ${e.data} ${Date.now()}`;
|
||||
sse.addEventListener('msg', (e) => {
|
||||
let Msg = JSON.parse(e.data);
|
||||
msg = `Msg: ${Msg.id} ${Msg.data} ${now()}`;
|
||||
console.log(msg);
|
||||
})
|
||||
|
||||
return () => {
|
||||
|
@ -62,11 +73,11 @@
|
|||
await fetch('/api/msg');
|
||||
}
|
||||
|
||||
async function ping() {
|
||||
async function Ping() {
|
||||
await fetch('/api/ping');
|
||||
}
|
||||
|
||||
async function pong() {
|
||||
async function Pong() {
|
||||
await fetch('/api/pong');
|
||||
}
|
||||
|
||||
|
@ -75,7 +86,21 @@
|
|||
|
||||
<h1>{msg}</h1>
|
||||
|
||||
<ul>
|
||||
<li>{jmsg.event}</li>
|
||||
<li>{jmsg.data}</li>
|
||||
<li>{jmsg.id}</li>
|
||||
</ul>
|
||||
<br>
|
||||
<h2>Ping: {dping}</h2>
|
||||
<br>
|
||||
<h2>Pong: {dpong}</h2>
|
||||
|
||||
|
||||
<button on:click={newmsg}>send Msg</button>
|
||||
<button on:click={ping}>send Ping</button>
|
||||
<button on:click={pong}>send Pong</button>
|
||||
<button on:click={Ping}>send Ping</button>
|
||||
<button on:click={Pong}>send Pong</button>
|
||||
|
||||
<hr>
|
||||
|
||||
<button on:click={Subscribe}>SSE Msg</button>
|
||||
|
|
Loading…
Add table
Reference in a new issue