SSE vs刷新js命令?

Roy*_*mir 4 javascript server-sent-events signalr

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);
}
Run Code Online (Sandbox Code Playgroud)

大.

但不是那么好.

我可以很容易地使用带有数据的JS命令(例如jsonp,也就是:使用回调对象类比填充),例如:_ cb(myMessage)

在客户端 - 同样处理它.(即使有更多欢迎mime类型,如application/javascript)

我可能在这里遗漏了一些东西.

  • SSE的优势是什么?

hal*_*r73 5

服务器发送事件(SSE)相对于JSONP /长轮询的最大优点是,只要接收到块,就可以读取SSE响应的每个块,而不需要完成响应.

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

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

现在,正如您在其中一条评论中提到的,您可以使用iframe而不是脚本标记来加载JavaScript有效内容.如果这样做,您可以发送回chunked响应并在响应完成之前执行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>
Run Code Online (Sandbox Code Playgroud)