SSE与刷新js命令

SSE vs flushing js commands?

本文关键字:命令 js 刷新 SSE      更新时间:2023-09-26

signalR的后备方案之一是SSE-服务器发送的事件。它所做的就是通过这个结构发送一条消息:

Message'n'n

所以在服务器端:

Response.ContentType = "text/event-stream";
while (startDate.AddMinutes(1) > DateTime.Now)
{
    Response.Write(string.Format("data: {0}'n'n", DateTime.Now.ToString()));
    Response.Flush();
    System.Threading.Thread.Sleep(1000);
}

太好了。

但不是很好。

我可以很容易地将JS命令与数据一起使用(比如jsonp用回调对象类比填充:(,例如:_cb(myMessage)

在客户方面,也要同样处理。(即使是更受欢迎的mime类型,如application/javascript(

我可能错过了什么。

  • SSE的优势是什么

与JSONP/long轮询相比,服务器发送事件(SSE(的最大优势在于,您可以在收到SSE响应的每个块后立即读取该块,而无需完成响应。

您可以使用分块响应来发回JSONP负载,但负责加载JSONP有效负载的<script src="...标记在整个响应完成之前不会执行JavaScript。在实践中,这意味着无论何时使用JSONP向客户端发送消息,都必须完成响应,以便客户端可以立即读取消息。

这反过来意味着客户端必须为接收到的每个消息发出一个新的JSONP请求(即向文档添加一个新脚本标记(。这就是为什么JSONP被认为是一个长轮询传输。

现在,正如您在一条评论中提到的,您可以使用iframe而不是脚本标记来加载JavaScript负载。如果这样做,可以发回分块响应,并在响应完成之前执行JavaScript,就像SSE一样。

事实上,这种隐藏的iframe技术正是SignalR用于其永久帧传输的技术。不幸的是,这种技术有几个缺点,导致SignalR在支持它的浏览器上更喜欢SSE:

  1. 隐藏iframe技术需要一个相对沉重的前奏*,因为您实际上是在发回HTML文档,而不是纯JavaScript。

  2. 除了函数调用之外,每个消息都需要封装在自己的脚本块中。(例如<script>c({"message": "myMessage"})</script>(。使用SSE,您只需要发送data: {"message": "myMessage"}'n'n,这会稍微高效一些。

  3. 最后,也许也是最重要的一点,隐藏的iframe消耗的内存在从DOM中删除之前永远不会被清除。这意味着,如果你不想无限增长内存,你必须定期创建一个新的iframe并删除旧的iframe。SSE传输使用的EventSource对象可以无限期地保持打开状态,而不会泄漏内存。

*SignalR永远的框架前奏:

<!DOCTYPE html><html><head><title>SignalR Forever Frame Transport Stream</title>
<script>
    var $ = window.parent.jQuery,
        ff = $ ? $.signalR.transports.foreverFrame : null,
        c =  ff ? ff.getConnection('1') : null,
        r = ff ? ff.receive : function() {};
        ff ? ff.started(c) : '';</script></head><body>