使用流JSON输出构建简单的nodejs API

时间:2014-10-27 11:18:13

标签: javascript json node.js socket.io streaming

我正在尝试构建一个简单的基于node.js的流API。我想要做的就是当我点击服务器URL时,输出应该流式传输一组测试数据(JSON),如twitter流API。

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(8083);

app.get('/', function (req, res) {
    res.write(io.on('connection', function (socket) {
              socket.emit('item', { hello: 'world' });
    }));
});

所以,如果我curl http://localhost:8083/,我希望输出类似于:

$ curl http://localhost:8083/
{hello: 'world'}
{hello: 'world'}
{hello: 'world'}
{hello: 'world'}
...

我是node.js和web套接字的新手。关于节点如何工作的基础知识,我可能会非常错误,让我知道最佳解决方案。

1 个答案:

答案 0 :(得分:2)

首先,将JSONStream部分放在像这样的中间件中会更好:

var _ = require('lodash');
// https://github.com/smurthas/Express-JSONStream/blob/master/index.js
function jsonStream(bytes) {
  return function jsonStream(req, res, next) {
    // for pushing out jsonstream data via a GET request
    var first = true;
    var noop = function () {};
    res.jsonStream = function (object, f) {
      f = _.isFunction(f) ? f : noop;
      if (!(object && object instanceof Object)) {
        return f();
      }

      try {
        if (first) {
          first = false;
          res.writeHead(200, {
            'Content-Type': 'application/json',
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive'
          });
        }
        res.write(JSON.stringify(object) + '\n');
      } catch (err) {
        return _.defer(f.bind(null, err));
      }
      f();
    };
    next();
  };
}

然后,我们假设您希望每次有人连接到socket.io时都会通过此API收到通知

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var _ = require('lodash');
var EventEmitter = require('events').EventEmitter;
server.listen(8083);

var mediator = new EventEmitter();

io.on('connection', function (socket) {
  mediator.emit('io:connection:new', socket);
});

// the second parameter, specify an array of middleware, 
// here we use our previously defined jsonStream
app.get('/', [jsonStream()], function (req, res) {

  function onNewConnection(socket) {
    res.jsonStream({
      type: 'newConnection',
      message: 'got a new connection',
      socket: {
        id: socket.id
      }
    });
  }

  // bind `onNewConnection` on the mediator, we have to use an mediator gateway
  // because socket.io does not offer a nice implementation of "removeListener" in 1.1.0
  // this way each time someone will connect to socket.io
  // the current route will add an entry in the stream
  mediator.on('io:connection:new', onNewConnection);

  // unbind `onNewConnection` from the mediator
  // when the user disconnects
  req.on('close', function () {
    mediator.removeListener('connection', onNewConnection);
  });

  res.jsonStream({
    type: 'welcome',
    message: 'waiting for connection'
  });
});

最后,如果要在不连接socket.io的情况下测试此代码,请使用以下模拟器:

// Simulate socket.io connections using mediator
(function simulate() {
  var dummySocket = {
    id: ~~(Math.random() * 1000)
  };
  mediator.emit('io:connection:new', dummySocket);
  setTimeout(simulate, Math.random() * 1000);
})();