如何使expressjs支持像facebook这样的批量请求

时间:2013-07-30 08:45:34

标签: node.js express

我有一组使用不同方法的路线。我想让expressjs支持批量请求,这与facebook Facebook Batch Request非常相似。有谁知道怎么做?我不想为处理批量请求制作3个环回连接。

1 个答案:

答案 0 :(得分:7)

如果您不想进行环回连接,那么最简单的解决方案是使用虚假请求手动调用您的服务器。

您必须重新实施IncomingMessage。您还应该使用Async#map等待处理所有请求。

这是基本想法:

// You'll probably have more work to do to reimplement http basic API.
function FakeRequest(request) {
  this.url = '/' + request.relative_url;
  this.method = request.method;
  this.headers = request.headers;
}

function FakeResponse() {
  Stream.call(this);

  this.statusCode = null;
  this.body = '';
}

FakeResponse.prototype.write = function (chunk) {
  this.body += chunk.toString('utf8');

  return true;
};

util.inherits(FakeResponse, Stream);

app.post('/', function (req, res) {
  var requests = JSON.parse(req.body.batch);

  async.map(requests, function (request, done) {
    var fakeReq = new FakeRequest(request),
        fakeRes = new FakeResponse();

    // call Express' middleware manually
    app(fakeReq, fakeRes);

    // this will trigger when the response is ready.
    fakeRes.once('end', function () {
      // don't leak listeners
      fakeRes.removeAllListeners();
      done(null, fakeRes);
    });

    fakeRes.once('error', function (err) {
      fakeRes.removeAllListeners();
      done(err);
    });
  }, function (err, responses) {
    if (err)
      return res.send(err);

    res.send(responses);
  });
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

<强>更新

我实际上不确定你的回环是什么意思,但你有两个选择:

  • 为批处理中的每个请求打开HTTP连接,这更容易实现但速度更慢。

  • 我上面概述的解决方案:直接调用Express中间件而不打开HTTP请求。

我的印象是你不想要第一个解决方案。然而,这就是我首先尝试的,即使它更慢:

  • 扩展时,可以更轻松地在多个实例之间传播批处理连接。
  • 您不会绕过任何可能的加载限制机制(阻止单个Express实例同时处理过多请求)。

请务必禁用HTTP Agent