服务端推送-SSE

更多看这里吧😁

概述

常见从服务端获取数据的方式有很多

  1. 轮询(长/短方式)
    就是客户端按照一定的频率定期向服务器获取数据,兼容性很好
  2. Comet
    主要获取数据的方式是长轮询和 iframe 流,不管是哪种都是通过建立长链接来使得服务器发送消息给客户端,前者使用轮询(每次轮询时候会一直等待直到服务端返回数据才关闭连接),后者使用页面的 iframe 标签的 src 属性向服务端建立长连接来获得数据。不过后期出现的 WebSocket 有取代 Comet 的趋势。
  3. WebSocket
    客户端和服务端通过”升级版“的 HTTP 协议进行全双工通信,服务端可以发送消息给客户端,客户端也可以发送消息给服务端,需要考虑兼容性。
  4. SSE
    是 Server sent event 的简写,服务端推送消息给客户端,但是客户端不能主动发送消息给服务端。并且基于 HTTP 协议,header部分有变化,需要考虑兼容性。

更多看这里吧😁

SSE 基本内容

概述

  1. SSE 通过 HTTP 协议使服务器推送数据给客户端。

  2. 在只要服务端而不用客户端发送数据的场景下可以考虑用。

    • 客户端一次请求但是返回数据量很大/慢,服务器分批次返回
    • 客户端请求服务器后需要回调通知
  3. 默认支持客户端自动断线重连。

  4. HTTP 的请求/响应头会有所不同,主要是这几个字段:

    request header

    Accept:text/event-stream
    

    response header

    Connection:keep-alive
    Content-Type:text/event-stream
    

    意思是请求的时候告诉服务器这是”事件流“,服务端响应我的连接是”长连接“,并且返回的数据是”文本的事件流“数据。

    服务端可能会多次返回数据,类型如下

    data:{"type":"COMMENT","keyList":["过去","gg"],"searchResponseItem":null}
    
    data:{"type":"CATEGORY","keyList":["过去","gg"],"searchResponseItem":null}
    
    data:{"type":"TAG","keyList":["过去","gg"],"searchResponseItem":null}
    
    data:{"type":"FRIEND_LINK","keyList":["过去","gg"],"searchResponseItem":null}
    
    data:{"type":"ARTICLE","keyList":["过去","gg"],"searchResponseItem":[]}
    
    event:finish
    data:stream finish
    

    在一次连接中服务器总共发送了 6 次数据,每一次一行,其中最后 2 行是一次发送,表达的是发送”finish“事件并且本次事件的数据是”stream finish“。

    具体数据格式怎么辨别可以查看文档

  5. 需要有一定兼容性的考量;当不使用 HTTP2 的时候,浏览器会对同个域下的 SSE 连接数进行限制为 6,如果是 HTTP2 则默认同个域下 100 个连接数,并且可以通过握手协商设置。

SSE 代码 Demo

客户端(以js为例)

const streamSearch = (): void => {
    const source = new EventSource("https://www.ahao.homes");

    source.onopen = () => {
        dev(() => console.log('start stream search...'));
        // 设置客户端超时事件
        const timeoutId = setTimeout(() => {
            // 如果超时了服务器还没返回则客户端关闭连接
            if (source.CLOSED !== source.readyState) {
                dev(() => console.log('stream search timeout...'));
                source.close();
            }
            clearTimeout(timeoutId);
        }, SEARCH_TIME_OUT);
    };

    source.onmessage = (e) => {
        dev(() => console.log(e.data));
    };

    // 客户端自定义的"finish"事件
    source.addEventListener('finish', () => {
        dev(() => console.log('finish stream search...'));
        source.close();
    });

    source.onerror = () => {
        dev(() => console.log('stream search error...'));
        source.close();
    };
};

其中

  1. new EventSource
new EventSource("https://www.ahao.homes");

表示向"https://www.ahao.homes"发送HTTP的GET请求来建立连接
这里似乎不能 POST 请求,并且不支持在 body 内部传入参数,只能通过将参数放到 url 内部方式传参,比如

new EventSource("https://www.ahao.homes/12345");
  1. readyState
0 — connecting
1 — open
2 — closed
  1. EventSource 的事件 API
方法名说明
onopen当建立连接的时候
onmessage当服务器发送的消息到达客户端的时候
onerror当连接发生异常的时候
  1. EventSource 的自定义事件 API
    source.addEventListener('finish', () => {
         dev(() => console.log('finish stream search...'));
         source.close();
     });
    
    自定义"finish"事件表示服务端发送的关闭连接事件

其余API介绍参考

服务端(以java的SpringBoot为例)

@GetMapping("/api/streamSearch/{key}")
    public SseEmitter streamSearch(@PathVariable String key) {
        // 创建SseEmitter类,并设置服务端的超时时间
        SseEmitter sseEmitter = new SseEmitter(SEARCH_TIME_OUT_MS);
        // 要在不同于主线程的线程里,不然似乎不可以
        new Thread(() => {

            // 服务器第一次发送数据
            sseEmitter.send(SseEmitter.event().data("data"));

            // 服务器第二次发送数据
            sseEmitter.send(SseEmitter.event().data("data"));

            ...

            // 服务器第n次发送数据
            sseEmitter.send(SseEmitter.event().data("data"));

            // 服务器发送"finish"事件并且数据是"stream finish"
            sseEmitter.send(SseEmitter.event().name("finish").data("stream finish"));
        }).start();
        return sseEmitter;
    }

其中
主要是运用SseEmitter这个类实现SSE。
这个类还有很多别的方法比如

  1. onCompletion()
  2. onError()
  3. onTimeout()

😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁

更多可以看这里

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值