SSE vs刷新js命令?

时间:2014-04-30 09:58:02

标签: javascript signalr server-sent-events

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有什么优势?

1 个答案:

答案 0 :(得分:5)

Server-sent events (SSE)相对于JSONP /长轮询的最大优点是,只要收到块,就可以读取SSE响应的每个块,而不需要完成响应。

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

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

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

事实上,这种hidden 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 object可以无限期保持打开而不会泄漏内存。

  4. * 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>