【前端】有时候你可能需要SSE而不是WebSocket

深度解析:轮询、SSE 和 WebSocket

在构建实时应用时,开发者面临多种选择,其中最常见的是轮询(Polling)、服务器推送事件(Server-Sent Events,SSE)和 WebSocket。本文将深入解析这三种技术的特点、适用场景及其兼容性,帮助您选择最合适的方案。
在这里插入图片描述


轮询 (Polling)
工作原理

轮询是一种简单直接的实现实时更新的方法,客户端通过定期发送 HTTP 请求到服务器,检查是否有新数据。这种方法易于实现,但其效率和延迟表现并不理想。

特点
  • 实现简单:客户端发送 HTTP 请求,服务器返回数据。
  • 延迟较高:由于客户端需要等待下一次轮询才能获取新数据。
  • 服务器负载高:频繁的请求增加了服务器的压力和带宽使用。
实例
function poll() {
    setInterval(function() {
        fetch('/data').then(response => response.json()).then(data => {
            // 处理数据
        });
    }, 5000); // 每5秒请求一次
}
poll();
适用场景

轮询适用于不需要实时更新且数据更新频率较低的场景,如定期状态检查或后台数据同步。

兼容性
  • 浏览器支持:所有现代浏览器和旧版浏览器都支持。
  • 服务器支持:任何支持 HTTP 的服务器都可以使用轮询。

服务器推送事件 (Server-Sent Events, SSE)
工作原理

SSE 允许服务器通过 HTTP 将实时更新的数据推送到客户端。客户端使用 EventSource 接口来接收这些更新。

特点
  • 单向通信:服务器向客户端推送数据。
  • 实现简单:基于 HTTP 协议,只需设置正确的 HTTP 头和响应格式。
  • 低延迟:服务器在数据更新时立即推送给客户端。
  • 自动重连:浏览器会自动处理重连机制。
实例

服务器端(Python Flask):

from flask import Flask, Response
import time

app = Flask(__name__)

@app.route('/stream')
def stream():
    def generate():
        while True:
            yield f"data: The time is {time.ctime()}\n\n"
            time.sleep(1)
    return Response(generate(), mimetype='text/event-stream')

if __name__ == '__main__':
    app.run(debug=True, threaded=True)

客户端(HTML + JavaScript):

<!DOCTYPE html>
<html>
<body>
    <div id="result"></div>
    <script>
        var source = new EventSource('/stream');
        source.onmessage = function(event) {
            document.getElementById('result').innerHTML += event.data + '<br>';
        };
    </script>
</body>
</html>
适用场景

SSE 适用于需要实时更新但不需要双向通信的场景,如新闻推送、股票价格更新等。

兼容性
  • 浏览器支持
    • 支持:Chrome 6+, Firefox 6+, Safari 5+, Opera 11+
    • 不支持:Internet Explorer,Edge 需 16+ 版本
  • 服务器支持:任何支持 HTTP 的服务器都可以实现 SSE。

WebSocket
工作原理

WebSocket 提供了一个持久化的连接,允许客户端和服务器之间进行实时的双向通信。相比于轮询和 SSE,WebSocket 具有更低的延迟和更高的效率。

特点
  • 双向通信:客户端和服务器之间可以实时传输数据。
  • 低延迟:通过保持持久连接,数据可以实时传输。
  • 复杂度高:需要额外的协议支持和更多的实现细节。
  • 资源效率高:相比轮询,WebSocket 的带宽和资源使用更高效。
实例

服务器端(Node.js):

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws) {
    ws.on('message', function incoming(message) {
        console.log('received: %s', message);
    });

    ws.send('something');
});

客户端(HTML + JavaScript):

<!DOCTYPE html>
<html>
<body>
    <script>
        var socket = new WebSocket('ws://localhost:8080');
        socket.onmessage = function(event) {
            console.log('Message from server ', event.data);
        };
        socket.onopen = function(event) {
            socket.send('Hello Server!');
        };
    </script>
</body>
</html>
适用场景

WebSocket 适用于需要实时双向通信的复杂应用,如在线游戏、即时聊天应用等。

兼容性
  • 浏览器支持
    • 支持:Chrome 16+, Firefox 11+, Safari 6+, Edge 12+, Opera 12.1+
    • 不支持:较老版本的浏览器(如 IE 10 以下)
  • 服务器支持:需要专门的 WebSocket 服务器或支持 WebSocket 协议的服务器。

总结一下

  • 轮询:实现简单、兼容性好,但效率低。适用于不需要实时更新的场景。
  • SSE:实现简单、单向通信、低延迟,但不支持 IE 浏览器。适用于需要实时更新的单向数据推送。
  • WebSocket:双向通信、低延迟、高效率,但实现复杂,对较旧的浏览器支持不佳。适用于需要实时双向通信的复杂应用。
  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值