处理连续的 JSON 流
(现已失效)页面 http://stream.twitter.com/1/statuses/sample .json 用于返回连续且无限的 JSON 数据流。
我想在我自己的网页中使用 jQuery(或 JavaScript,但最好是 jQuery)对其进行处理,以便能够根据推文的实时提要显示视觉效果。
据我所知,jQuery parseJSON
函数只会在服务器发送完所有数据后才会执行回调函数,但这实际上是一个连续的数据流。如何“在发生时”处理数据但仍保持连接运行?
The (now defunct) page http://stream.twitter.com/1/statuses/sample.json used to return a continuous and endless stream of JSON data.
I'd like to process it using jQuery (or JavaScript, but preferably jQuery) inside my own web page to be able to display visual effects based on the live feed of tweets.
Since as far as I know the jQuery parseJSON
function will only execute the callback function after all the data has been sent by the server, but this is actually a continuous stream of data. How can I process the data "as it happens" but still keep the connection running?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这种事情现在最好使用 WebSockets 来完成,根据 CanIUse .Com 可在所有主要浏览器中使用,除了 Opera Mini(请参阅该链接有关旧版或所有浏览器的更多详细信息,然后单击“资源”选项卡查看更多链接)。总体而言,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 和 Web Workers 也是如此,尽管它们有不同的用例和不同的能力。
它看起来像这样:
发送消息变得如此简单:
请参阅WebSocket 简介:将套接字引入 Web 有关如何执行此操作的完整说明。
ASP.Net 开发人员:如果由于某种原因您需要支持较旧的浏览器,并且不想自己弄清楚如何处理那些不支持 WebSocket 的浏览器,请考虑使用诸如 SignalR。
针对较旧浏览器的旧 EventSource API 答案
大多数浏览器现在都实现 EventSource API,只要可以使用内容类型
text/event-stream
传递流,就可以使长轮询变得非常简单。较旧的浏览器或因任何原因无法设计流以具有该内容类型的开发人员可以使用一些 帮助程序脚本 做同样的事情。这是一个例子:
这基本上是我在下面概述的内容的完整版本。
针对非常旧的浏览器的更旧的服务流解决方案
您想要的称为长轮询。您需要一个自定义 AJAX
onreadystatechange
处理函数。您需要定期检查内容,而不是等到整个流完成(因为它永远不会完成)。请注意,您需要使用iframe
进行一些繁重的工作才能在 IE 9 及更低版本中工作。粗略地:
onreadystatechange
事件并检查分配给当前角色的流,以查看是否有足够的数据来消耗一个或多个离散事件。您需要使用 JavaScript 字符串处理函数自行解析流。可以使用 split、indexOf、正则表达式、循环等组合来完成此任务。onreadystatechange
处理程序触发时,responseText
将是迄今为止收到的所有数据。定义一个持久变量,用于保存尚未正确处理的第一个字符的位置。查看此 HTTP Streaming gist 了解一项资源,或 流式传输作为轮询的替代方法服务器位于SoftwareAs。如果您必须支持 IE 9 或更早版本,则需要使用
iframe
方法。这是 引自这本书Ajax 设计模式:使用编程和可用性模式创建 Web 2.0 站点:
请注意,它是 2006 年的,所以它肯定已经过时了,但如果您必须支持较旧的浏览器,它仍然相关。
安全问题
正常的 AJAX 不能跨域,这意味着(现在我注意到你想从 twitter 流式传输)你将无法执行你所要求的操作。这可以通过 JSONP 来解决,但 JSONP 本质上不能进行服务流传输,而且 Twitter 也不提供这种服务。还有跨源资源共享 (CORS),但 Twitter 不会为您进行设置 - 这是他们只会为附属于他们的域所做的事情。 CORS 需要现代浏览器。
因此,您唯一的选择是在您的 Web 服务器上创建一个代理服务,该服务为您执行对 twitter 的请求,然后分发数据。这只能从提供主页的同一域中完成。这样做还可以让您使用 iframe 技术创建一个适用于 IE 的版本。如果您不关心旧的 IE 版本,并且知道将发出请求的域,则可以自行实施 CORS 来克服域限制。
如果您完全控制客户端软件(例如,如果这是用于公司内部网),则还有另一种选择:将 Web 浏览器托管在已编译的本地执行应用程序的用户表单内。我只使用 C# 完成了此操作,但我认为其他语言也可以做到这一点。当您使用正确的浏览器对象时,因为它托管在 C# 应用程序内,所以 C# 应用程序可以克服跨域安全限制,读取和写入所有页面内容,无论它来自哪个域。我怀疑你的情况是这样的,但我想把这个选项放在这里,供其他可能会欣赏它的人使用。
This sort of thing is best done using WebSockets now, which according to CanIUse.Com is available in all major browsers except Opera Mini (see that link for more details about older or all browsers, and click the Resources tab to see even more links). As an overview, websockets are supported in IE 10+, Edge 12+, Firefox 11+ (38+ if within a WebWorker context), Chrome 16+, Opera 12.1+, Safari 7+, Android 4.4+, Opera Mobile 12.1+.
Note: you will likely want to learn about Service Workers and Web Workers as well, though those have different use cases and different abilities.
It looks like this:
Sending messages becomes as easy as this:
See Introducing WebSockets: Bringing Sockets to the Web for a full explanation on how to do this.
ASP.Net developers: if for some reason you need to support older browsers and don't want to figure out for yourself how to deal with those that don't support WebSockets, consider using a library such as SignalR.
The Old EventSource API Answer For Older Browsers
Most browsers now implement the EventSource API, which makes long polling really easy, as long as the stream can be delivered with content-type
text/event-stream
. Older browsers or those developers who for any reason can't engineer the stream to have that content-type can use some helper script to do the same thing.Here's an example:
This is basically a full-fledged version of the exact thing that I outline below.
The Even Older Service Streaming Answer For REALLY OLD Browsers
What you want is called long polling. You'll need a custom AJAX
onreadystatechange
handling function. Instead of waiting until the entire stream has completed (since it never will), you'll need to examine the contents periodically. Note that you'll need to do some heavy lifting for this to work in IE 9 and lower, using aniframe
.Roughly:
onreadystatechange
event and examine the stream you've been given up to the current character to see if there is enough data to consume one or more discrete events. You'll need to parse the stream yourself with javascript string-handling functions. A combination of split, indexOf, regular expressions, looping, and so on can be used to accomplish this task.onreadystatechange
handler fires, theresponseText
will be all the data that has been received so far. Define a persistent variable that will hold the position of the first character that hasn't been properly processed yet.Check out this HTTP Streaming gist for one resource, or Streaming as an alternative to polling the server at SoftwareAs. If you must support IE 9 or older, then you'll need to use the
iframe
method for that.Here is a quote from the book Ajax Design Patterns: Creating Web 2.0 Sites with Programming and Usability Patterns:
Mind you that it is from 2006, so it is definitely out of date, but if you have to support older browsers, it's still relevant.
Security Issues
Normal AJAX cannot go cross-domain, meaning (now that I pay attention to the fact that you want to stream from twitter) that you won't be able to do what you're asking. This can be worked around with JSONP, but JSONP by nature can't be service streamed and moreover isn't offered by twitter anyway. There is also Cross-Origin Resource Sharing (CORS) but twitter's not going to set that up for you--that's the kind of thing they'd only do for domains affiliated with them. And CORS requires a modern browser.
Your only option is thus to create a proxy service on your web server that performs the requests to twitter for you and then hands out the data. This can only be done from the same domain as the main page was served from. Doing this would also allow you to create a version that will work for IE using the iframe technique. If you don't care about old IE versions, you can implement CORS yourself to defeat the domain restriction, if you know the domain that will be making the requests.
If you have full control of the client software (like if this is for a corporate intranet) there is another option: hosting the web browser inside of a compiled locally-executed application's user form. I have only done this using C# but I imagine it's possible from other languages. When you use the right browser object, because it's hosted inside a C# application, the C# application can defeat the cross-domain security restrictions, reading and writing all page content no matter what domain it comes from. I doubt your situation is this one but I wanted to put the option here for others who might appreciate it.
我有一个开源项目,它允许在现代浏览器上执行此操作(并在旧浏览器上回退到 jQuery 样式)。调用语法类似于 jQuery.ajax:
http://oboejs.com
I've got an open source project which allows this on modern browsers (and falls back to a jQuery-style on older ones). The call syntax is similar to jQuery.ajax:
http://oboejs.com
您在问题中指定的 url 会发送 JSON 响应流。由于浏览器中的跨域安全限制,您无法使用 javascript 访问它。您需要在服务器上实现一个桥接服务器端脚本,您可以使用 AJAX 请求定期轮询或在
twitter.com
上托管您的网站。第一种似乎更可行。The url you have specified in your question sends a JSON response stream. Due to cross domain security restrictions in browsers you cannot access it using javascript. You will need to implement a bridge server side script on your server which you could poll at regular intervals using AJAX requests or host your site on
twitter.com
. The first seems more feasible.如今,Fetch API 支持流式传输。
body
属性它的响应是一个 ReadableStream。一般来说,有两种流式传输 JSON 的方法,我不知道 Twitter 使用的是哪一种:一种是发送单个 JSON 文档,该文档是或包含一个数组/对象,其属性/元素作为流发送。另一个是 JSON 流,其中多个 JSON 文档按顺序发送,通常由空白字符。 JSON 行 是一种标准,其中 JSON 文档由换行符分隔,并且 JSON-seq 是一个标准,它们由
0x1E
记录分隔符。json-stream-es 是一个 JavaScript 库,支持解析任何格式的流式 JSON上面的格式。例如,JSONL 流将被解析如下:
Nowadays, the Fetch API supports streaming. The
body
property of its response is a ReadableStream.Generally speaking, there are two ways of streaming JSON, and I don’t know which one Twitter was using: One is to send a single JSON document that is or contains an array/object whose properties/elements are sent as a stream. The other is a JSON stream, where multiple JSON documents are sent in sequence, often delimited by a whitespace character. JSON Lines is a standard where the JSON documents are delimited by a newline, and JSON-seq is a standard where they are delimited by a
0x1E
record separator character.json-stream-es is a JavaScript library that supports parsing streamed JSON in any of the formats above. For example, a JSONL stream would be parsed like this:
从根本上讲,网页无法保持与服务器的实时/运行连接。 Web 浏览器向服务器发送请求。服务器将响应(HTML 等)发送回客户端(Web 浏览器)。将此视为无状态模型 - 在请求和响应完成后,任何连接都不会保持活动状态。
因此,你必须自己做。您必须从客户端调用额外的定期请求。
一种方法是通过 setInterval() 函数定期调用 AJAX/GET 功能。例如:
这将每 5 秒触发一次对 mydata/get(或您想要使用的任何 URL)的 AJAX 请求。
A web page at a very fundamental level can't keep a live/running connection to a server. Web browser sends a request to the server. Server sends a response (the HTML and more) back to the client (web browser). Think of this as a stateless model - no connection is ever kept alive after the request and response have been completed.
Therefore, you have to do it yourself. You have to invoke additional, periodic requests from the client-side.
One way would be to periodically call your AJAX/GET functionality via setInterval() function. For example:
This will fire off an AJAX request to mydata/get (or whatever URL you want to use) every 5 seconds.