Skip to main content

SSE 与 postMessage 相似

是的,SSE(服务器推送)和 postMessage(跨文档通信)基本可以看作是同一时代的技术,它们都随着 HTML5 标准的浪潮,在2000年代末期诞生于浏览器世界。因为都利用了 message 事件,所以在开发者的使用体验上感觉很相似,但两者的实际用途截然不同。

🧬 一段平行的浏览器技术史

两者就像同时起步,但走向了不同方向的“同学”:

  • 🥇 酝酿与雏形 (约2004年 - 2009年)

    • postMessage: 2008年被提出并进入HTML5草案,旨在解决阻碍网页灵活性的“同源政策”。早在2009年便已提出草案。
    • SSE: 受当时“Comet”实时推送技术启发,于2006年在Opera浏览器中作为实验性功能出现。2008-2009年正式被纳入WHATWG的HTML5草案和W3C标准流程。
  • 🚀 发展与应用 (约2009年 - 2015年)

    • 这是HTML5标准逐步成熟的阶段。各主流浏览器(Chrome, Firefox等)开始纷纷实现对这两个API的实验性或基本支持。
    • postMessageSSE 在这个时期随着Web应用复杂度的提升,各自的实用价值开始凸显。
  • 🎯 成熟与标准化 (约2015年以后)

    • 2015年 是一个关键节点:
      • 同年7月起,window.postMessage 获得了所有主流浏览器的完整、广泛支持。
      • W3C也在2015年2月正式发布了 SSE 的官方推荐标准。
    • 至此,两者均已成为现代Web开发中成熟、稳定且被广泛使用的标准技术。

🌉 “长得像”,因为它们共享一个“家”

它们让开发者感觉很相似,主要是因为三点:

  1. 都是“亲儿子”SSEpostMessage 都是 HTML5 规范 这个官方标准体系内的技术。它们从设计之初就是为了解决Web开发的特定问题,因此也共享了一些标准化的设计模式和API风格。

  2. 事件驱动模型:两者都采用了浏览器原生的事件监听机制来传递数据。它们都使用类似的 onmessage 事件处理器来接收信息,这让API看起来非常直观。

    // postMessage 接收消息
    window.addEventListener('message', (event) => {
    console.log('收到消息:', event.data);
    });

    // SSE 接收消息 (也是 message 事件)
    const source = new EventSource('/stream');
    source.onmessage = (event) => {
    console.log('收到推送:', event.data);
    };
  3. 独立于传输层message 事件对象是一个高层次的浏览器API,对底层传输细节(HTTP帧、TCP包等)进行了封装。无论是网络通信(SSE)还是进程间通信(postMessage),开发者都通过统一的 message 事件接口进行交互。

🔎 为什么它们不是替代品?核心差异在这里

尽管API用法相似,但它们的本质完全不同,服务于完全不同的场景。

  • postMessage 是一个纯粹的前端、浏览器内部通信工具
  • SSE 是一个网络协议,用于浏览器与服务器之间的通信。
特性postMessageSSE (Server-Sent Events)
主要职责解决跨源/跨窗口/跨线程的前端通信实现服务器向浏览器的实时、单向数据推送
通信范围同一浏览器内的不同页面iframeWeb Worker 之间浏览器 → 服务器 (网络层)
数据传输支持复杂的数据类型(对象、数组等),通过结构化克隆算法传输通过HTTP长连接传输文本流 (通常是JSON字符串)
连接性质无连接(瞬时调用),无须建立长连接基于HTTP的持久长连接,连接一直保持以接收推送
安全模型通过 targetOrigin 参数精确控制接收域,提供跨域安全通信遵循浏览器的 同源策略,无法向跨域地址发起连接

📝 一个帮助你快速区分的比喻

你可以想象一个“社区”(浏览器):

  • postMessage 就像是社区里不同住户(网页、iframe)之间的内部电话系统,用来交流八卦、商量事情。
  • SSE 则像是社区门口的广播站大喇叭。广播站(服务器)一旦响起,所有在家里开着收音机(EventSource 连接)的住户都能听到实时消息。不过,住户没法用大喇叭跟广播站对话,只能被动收听。

如果对它们的某些特性或实际用法还有疑问,随时可以再问我~