【问题标题】:Process a continuous stream of JSON处理连续的 JSON 流
【发布时间】:2011-09-27 08:07:46
【问题描述】:

(现已失效)页面 http://stream.twitter.com/1/statuses/sample.json 用于返回连续且无穷无尽的 JSON 数据流。

我想在我自己的网页中使用 jQuery(或 JavaScript,但最好是 jQuery)对其进行处理,以便能够根据推文的实时提要显示视觉效果。

据我所知,jQueryparseJSON函数只有在服务器发送完所有数据后才会执行回调函数,但这实际上是一个连续的数据流。如何在“发生时”处理数据但仍保持连接运行?

【问题讨论】:

  • jQuery 1.6.2 支持流处理了吗?我在文档中找不到任何内容。

标签: javascript jquery json stream


【解决方案1】:

一个非常基础的网页无法保持与服务器的实时/运行连接。 Web 浏览器向服务器发送请求。服务器将响应(HTML 等)发送回客户端(Web 浏览器)。将其视为无状态模型 - 在请求和响应完成后,任何连接都不会保持活动状态。

因此,您必须自己做。您必须从客户端调用额外的定期请求。

一种方法是通过setInterval() 函数定期调用您的AJAX/GET 功能。例如:

setInterval(function() {

    $.ajax({
      url: "mydata/get",
      success: function(){
        // update content.
      }
    });

}, 5000);

这将每 5 秒向 mydata/get(或您要使用的任何 URL)发出 AJAX 请求。

【讨论】:

  • 我认为您完全错过了所要求的内容。
  • @ErikE,那你为什么不解释一下?
  • 我需要实时数据,每 5 秒执行一次请求是行不通的,并且执行太多会非常糟糕
  • 就像我说的,在网页的生活中没有“生活”这样的东西。只能从页面拉取数据,不能推送到页面上。
  • 您能否在回答中详细说明这些不利影响和风险?
【解决方案2】:

您在问题中指定的网址会发送 JSON 响应流。由于浏览器中的跨域安全限制,您无法使用 javascript 访问它。您将需要在您的服务器上实现一个桥接服务器端脚本,您可以使用 AJAX 请求定期轮询或在twitter.com 上托管您的站点。第一个似乎更可行。

【讨论】:

  • 我能达到的最小间隔是多少?我需要它非常快。
  • @Gabriele Cirulli,你说的最小间隔是多少?轮询间隔?这将取决于您的客户端浏览器与服务器的网络连接速度以及呈现 DOM 元素的能力。
  • JSONP 可以解决跨域安全问题,但我想服务流将无法正常工作。
  • @ErikE,这个 twitter 流 API 不支持 JSONP。
  • 没错,达林,我就是这个意思。
【解决方案3】:

这种事情现在最好使用WebSockets 来完成,根据 CanIUse.Com 的说法,除了 Opera Mini 之外,它是 available in all major browsers(有关旧版或所有浏览器的更多详细信息,请参阅该链接,然后单击资源选项卡以查看更多链接)。总的来说,IE 10+、Edge 12+、Firefox 11+(如果在 WebWorker 上下文中,则为 38+)、Chrome 16+、Opera 12.1+、Safari 7+、Android 4.4+、Opera Mobile 12.1+ 支持 websocket。

注意:您可能还想了解 Service Workers and Web Workers,尽管它们有不同的用例和不同的能力。

看起来像这样:

var connection = new WebSocket(
   'ws://html5rocks.websocket.org/echo',
   ['soap', 'xmpp']
);

立即将一些事件处理程序附加到连接上,可以让您知道连接何时打开、何时收到传入消息或是否发生错误。

发送消息就这么简单:

connection.send('your message');
connection.send(binaryData);

有关如何执行此操作的完整说明,请参阅 Introducing WebSockets: Bringing Sockets to the Web

ASP.Net 开发人员:如果由于某种原因您需要支持较旧的浏览器并且不想自己弄清楚如何处理那些不支持 WebSockets 的浏览器,请考虑使用诸如 SignalR 之类的库。

旧版浏览器的旧 EventSource API 答案

现在大多数浏览器都实现了EventSource API,这使得长轮询非常容易,只要流可以使用内容类型text/event-stream 传递。较旧的浏览器或那些因任何原因无法将流设计为具有该内容类型的开发人员可以使用一些 helper script 来做同样的事情。

这是一个例子:

var jsonStream = new EventSource('https://example.com/yourstreamingservice')
jsonStream.onmessage = function (e) {
   var message = JSON.parse(e.data);
   // handle message
};

这基本上是我在下面概述的确切内容的完整版本。

针对真正旧浏览器的更旧的服务流式处理解决方案

您想要的称为长轮询。您将需要一个自定义 AJAX onreadystatechange 处理函数。您需要定期检查内容,而不是等到整个流完成(因为它永远不会完成)。请注意,您需要做一些繁重的工作才能在 IE 9 及更低版本中使用 iframe

大致:

  • 响应每个onreadystatechange 事件并检查您已放弃给当前字符的流,以查看是否有足够的数据来消耗一个或多个离散事件。您需要使用 javascript 字符串处理函数自己解析流。可以使用 split、indexOf、正则表达式、循环等的组合来完成此任务。
  • 如果内容还不够,则退出并等待下一个事件。
  • 我很确定,每次onreadystatechange 处理程序触发时,responseText 将是迄今为止收到的所有数据。定义一个持久变量,该变量将保存尚未正确处理的第一个字符的位置。
  • 一旦有足够的内容让一个或多个离散事件出现在流中,一次取出一个并将它们传递给您的 JSON 解析器,以实际将文本呈现为对象。正常使用。

查看此HTTP Streaming gist 以获得一种资源,或查看 SoftwareAs 的Streaming as an alternative to polling the server。如果您必须支持 IE 9 或更早版本,则需要为此使用 iframe 方法。

这里是a quote from这本书Ajax Design Patterns: Creating Web 2.0 Sites with Programming and Usability Patterns

总之,Service Streaming 使 HTTP Streaming 方法更加灵活,因为您可以流式传输任意内容而不是 Javascript 命令,并且因为您可以控制连接的生命周期。但是,它结合了两种跨浏览器不一致的技术,并具有可预测的可移植性问题。实验表明,页面流技术确实适用于 IE [9 和更早版本] 和 Firefox,但服务流仅适用于 Firefox,无论使用 XMLHTTPRequest 还是 IFrame。在第一种情况下,IE [9 和更早] 会抑制响应直到它完成,如果使用解决方法,它可以使用 IFrame:IE [9 和更早] 在前 256 个字节之后接受来自服务器的消息,所以唯一的事情要做的是在发送消息之前发送 256 个虚拟字节。在此之后,所有消息将按预期到达。因此,在 IE [9 及以上] 中也可以实现完整的 Service Streaming!

请注意,它是从 2006 年开始的,所以它肯定已经过时了,但是如果你必须支持旧版浏览器,它仍然是相关的。

安全问题

普通的 AJAX 不能跨域,这意味着(现在我注意到您想要从 twitter 流式传输的事实)您将无法按照您的要求进行操作。这可以通过 JSONP 解决,但 JSONP 本质上不能被服务流式传输,而且 Twitter 也不提供。还有Cross-Origin Resource Sharing (CORS),但 twitter 不会为您设置 - 这是他们只会为与他们关联的域做的事情。而且 CORS 需要现代浏览器。

因此,您唯一的选择是在您的 Web 服务器上创建一个代理服务,该服务为您执行对 twitter 的请求,然后分发数据。这只能在与提供主页的域相同的域中完成。这样做还允许您使用 iframe 技术创建适用于 IE 的版本。如果您不关心旧的 IE 版本,如果您知道将发出请求的域,则可以自己实现 CORS 以克服域限制。

如果您可以完全控制客户端软件(例如,如果这是用于公司 Intranet),则还有另一种选择:将 Web 浏览器托管在已编译的本地执行应用程序的用户表单中。我只使用 C# 完成了这项工作,但我想其他语言也可以。当您使用正确的浏览器对象时,因为它托管在 C# 应用程序中,所以 C# 应用程序可以克服跨域安全限制,读取和写入所有页面内容,无论它来自哪个域。我怀疑您的情况是这种情况,但我想将选项放在这里,以供可能会欣赏它的其他人使用。

【讨论】:

  • EventSource 仅适用于 text/event-stream content-type: html5rocks.com/en/tutorials/eventsource/basics
  • @GabrieleCirulli 你是2048 fame 的Gabrielle Cirulli 吗?我很荣幸能帮到你! :)
  • HTTP 流媒体链接已失效。
  • @Tyler 谢谢,已修复。如果您发现任何其他问题,请告诉我!
【解决方案4】:

我有一个开源项目,它允许在现代浏览器上执行此操作(并且在旧浏览器上回退到 jQuery 样式)。调用语法类似于jQuery.ajax:

http://oboejs.com

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2021-01-14
  • 1970-01-01
  • 2017-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多