Lightstreamer 背后的魔力是啥?
Posted
技术标签:
【中文标题】Lightstreamer 背后的魔力是啥?【英文标题】:What is the magic behind Lightstreamer?Lightstreamer 背后的魔力是什么? 【发布时间】:2012-05-15 03:20:29 【问题描述】:我要开发一个彗星编程框架,但我不能使用 Web Sockets 或服务器发送事件(因为浏览器支持真的很烂)。因此,我需要保持 HTTP 连接处于活动状态,并将分块数据发送回客户端。
但是,当您开始工作时,问题就会显现出来:
-
使用 XMLHttpRequest 是不可能的,因为 IE 没有给你
xhr.responseText
而xhr.readyState
是 3。
隐藏的iframe
没有用处,因为当我将数据发送回客户端时,浏览器会显示加载器。
我尝试将 javascript 文件发送回客户端,每次都发送函数执行命令,但浏览器在完全加载之前不会执行 JavaScript。
但是,当我查看Lightstreamer demo page 时,我看到它会一点一点地向客户端发送一个 JavaScript 文件,并且在每一步中,它都会发送一个对函数的调用,然后该函数就会被执行(我可以' t 做这部分)。似乎 Lightstreamer 使用 AJAX,因为请求只是显示在 Firebug 的控制台选项卡中,但它在 IE 中也像一个魅力。
我尝试使用他们在请求中设置的每个 HTTP 标头字段,但没有结果。我也尝试使用 HTTP Post 而不是 HTTP Get,但仍然没有结果。
我已经阅读了近 20 多篇关于如何实现 comet 的文章,但似乎没有一篇能解决我遇到的问题:
-
如何让它跨浏览器?
当新数据从服务器到达时如何得到通知(我应该挂钩什么事件)?
如何让我的页面向用户显示为已完全加载(如何实现,以便浏览器不显示加载活动)?
有人可以帮忙吗?我认为应该有一个我不知道的小技巧或窍门将所有概念粘合在一起。有谁知道 lightstreamer 是如何解决这些问题的?
【问题讨论】:
【参考方案1】:这里是 SockJS 作者。
如何让它跨浏览器?
这很难,预计要花几个月的时间在 Opera 和 IE 上获得流传输。
当新数据从服务器到达时如何得到通知(我应该挂钩什么事件)?
有多种技术,具体取决于特定的浏览器。了解一下 Socket.IO 和 SockJS 支持的不同回退协议。
如何让我的页面向用户显示为已完全加载(如何实现,以便浏览器不显示加载活动)?
同样,还有一些特定于浏览器的技巧。一种是在 onload 事件之后延迟加载 AJAX。其他是从 DOM 绑定和取消绑定 iframe。等等。如果您仍然感兴趣,请阅读 SockJS 或 Socket.io 代码。
有人可以帮忙吗?我认为应该有一个我不知道的小技巧或窍门将所有概念粘合在一起。有谁知道 lightstreamer 是如何解决这些问题的?
基本上,除非您有非常充分的理由,否则不要重新发明***。使用 SockJS、Socket.io、faye 或任何其他已经解决此问题的项目。
【讨论】:
Marek,问题是“lightstreamer 的魔力是什么”——你是说 SockJS 之类的魔力是什么? (例如,我们不需要 lightstreamer,因为 SockJS 处理跨平台 JS 客户端)?那 lightstreamer 服务器呢,它有什么魔力吗? 我问这个问题是因为:***.com/questions/19667644/…【参考方案2】:您想要的方法是streaming。
如何让它跨浏览器?
考虑到大多数浏览器,没有一致的方法。您必须根据浏览器选择合适的传输方式。更糟糕的是,您必须依靠浏览器嗅探来识别正在使用的浏览器,而功能检测对此毫无意义。您可以将 XDomainRequest 用于 IE8+,XMLHttpRequest 用于非 IE,Iframe 用于 IE 6+。尽可能避免 iframe 传输。
当新数据从服务器到达时如何得到通知(我应该挂钩什么事件)?
这取决于所使用的传输方式。例如,XDomainRequest 触发进度事件,XMLHttpRequest 在块到达时触发 readystatechange 事件,除了 Opera 和 IE。
如何让我的页面显示为完全加载给用户(如何实现它,以便浏览器不显示加载活动)?
我不知道 iframe 的这个问题,但仍然会在基于 WebKit 的浏览器中出现,例如带有 XMLHttpRequest 的 Chrome 和 Safari。避免这种情况的唯一方法是在 window 的 onload 事件之后进行连接,但是对于 Safari,这不起作用。
除了以上问题,还有一些问题你需要考虑。
-
事件驱动服务器 - 服务器应该能够异步处理。
传输要求 - 服务器对所需传输的行为有所不同。
流格式 - 如果服务器要在单个块中发送大消息或多条消息,则单个块并不意味着单个数据。它可以是单个数据的片段或多个数据的串联。要识别什么是数据,应对响应进行格式化。
错误处理 - Iframe 传输不提供任何断开连接的证据。
...
最后但并非最不重要的一点,与长轮询相比,实现流式传输相当令人厌烦。我建议您使用可靠的框架来执行此操作,例如我创建和管理的socketio、sockjs 和jquery socket。
祝你好运。
【讨论】:
【参考方案3】:但浏览器在 JavaScript 完全加载之前不会执行它。
您是否尝试过发回包裹在<script>
标签中的代码?例如,而不是:
<script type="text/javascript">
f(...data1...);
f(...data2...);
试试
<script type="text/javascript">f(...data1...);</script>
<script type="text/javascript">f(...data2...);</script>
【讨论】:
是的,我试过了,但只有将 MIME 类型设置为 text/html 才有效。换句话说,您应该请求另一个 HTML 文档。如果您将响应设置为 application/javascript 或 application/x-javascript 或 text/javascript 它将不起作用。也解决不了我的问题。我可以使用 XMLHttpRequest 请求包含 JavaScript sn-ps 的 HTML 文件。但是,它在 IE 中不起作用。我可能会使用iframe
,但它会显示加载程序。 Lightstreamer 可以在任何地方工作,并且不显示加载程序标志。
另外请注意,如果我使用XMLHttpRequest
获取包含<script>alert('loaded');</script>
JavaScript sn-ps 的不断加载的HTML 文件,它们将不会被执行。我的意思是,浏览器会在 JavaScript 标记到达时执行 JavaScript 代码,但仅限于普通请求,而不是 ajax 请求。【参考方案4】:
在您的情况下,最好的选择是在服务器端使用 JSONP + Long Pulling。您只需要记住在连接断开(超时)或收到响应时重新连接。
jquery 中的示例代码:
function myJSONP()
$.getScript(url,
success: function()
myJSONP(); //re-connect
,
failure: function()
myJSONP(); //re-connect
)
很明显,您来自服务器的响应必须是调用您的全局函数的 javascript 代码。
或者,您可以使用一些 jquery JSONP 插件。
或者看看这个项目http://www.meteor.com/(真的很酷,但没试过)
【讨论】:
我不想每次更新都建立一个连接(请求)。我只需要打开一个连接,并通过该单个连接更新客户端的浏览器。请参阅我的问题中的链接并在 Firebug 中检查它。以上是关于Lightstreamer 背后的魔力是啥?的主要内容,如果未能解决你的问题,请参考以下文章