Node.js - 解析分块传输的 Twitter JSON 数据

6

Node.js服务器从Twitter获取此JSON流并将其发送给客户端:

stream.twitter.com/1/statuses/filter.json?track=gadget

客户端返回的数据是“分块”JSON。在客户端上使用JSON.parse(chunk)和eval('('+ chunk +')')都会导致解析错误。拼接分块数据并等待“end”事件也不是一个解决方案。我注意到以前的示例在客户端上使用了类似这样的东西,显然以前可以工作:
  socket.onmessage = function(chunk) { 
  data = eval("(" + chunk.data + ")");
  alert(data.user.screen_name);

我正在客户端使用这个,但结果却出现了解析错误:
var socket = new io.Socket();
    socket.on('message', function(chunk) { 
    var data = eval('(' + chunk + ')'); // parsing error
    alert(data.screen_name): 

我知道它能成功返回一个JSON代码块:

  var socket = new io.Socket();
        socket.on('message', function(chunk) {  
        alert(chunk): // shows a JSON chunk

服务器:

  response.on('data', function (chunk) {
    client.each(function(e) {
      e.send(chunk);  
  });  

有什么变化或我做错了什么吗?

更新:'end'事件没有触发是因为它正在流式传输?

http.get({
  headers: { 'content-type': 'application/json' },
  host: 'stream.twitter.com',
  path: '/1/statuses/filter.json?track...
}, function(res) {

  res.setEncoding('utf8');
  res.on('data', function (chunk) {
    client.each(function(e) {
      e.send(chunk);  
  });  
 });

  // does not fire
  res.on('end', function () {

  });  

...

我正在研究http 1.0和http 1.1在发送分块数据方面的区别。


2
你确定连接块并等待结束事件不起作用吗?我认为这是应该这样做的,因为它无法解析接收到的半块。 - neebz
3个回答

15

请查看Twitter文档中标题为“解析响应”的部分。

从Streaming API解析JSON响应很简单,每个对象都单独返回在一行上,并以回车符结束。换行符(\n)可能出现在对象元素中(例如状态对象的文本元素),但不应该有回车符(\r)。

在服务器端,继续累积块,直到看到回车符"\r"。一旦找到回车符,提取到回车符之前的字符串即可获取一个推文。

var message = ""; // variable that collects chunks
var tweetSeparator = "\r";

res.on('data', function(chunk) {
    message += chunk;

    var tweetSeparatorIndex = message.indexOf(tweetSeparator);
    var didFindTweet = tweetSeparatorIndex != -1;

    if (didFindTweet) {
        var tweet = message.slice(0, tweetSeparatorIndex);
        clients.forEach(function(client) {
            client.send(tweet);
        });
        message = message.slice(tweetSeparatorIndex + 1);
    }
});
客户端变得简单。只需将套接字消息完全解析为JSON即可。
socket.on('message', function(data) {
    var tweet = JSON.parse(data);
});

我认为应该是 message.split("\r").forEach(function(tweet)。 - user713886

2

@Anurag,我无法添加评论,但是可以尝试这个方法:

if (chunk.substr("-1") == "\r") 

应该是这样:

if ( chunk.charCodeAt(chunk.length-2) == 13 )

回车符不是最后一个字符。

谢谢指出这一点。我稍微改了一下我的实现。Twitter的块并不总是以换行符或回车符结尾。 - Anurag

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接