服务端事件(SSE)未到达客户端

7
我正在使用MEAN技术栈,并尝试从服务器端接收事件。为此,我使用了EventSource,但它似乎无法正常工作。
我可以看到连接已打开,但是没有从服务器获取任何消息。我可以在Node控制台中看到消息被发送,但在客户端(浏览器控制台)中却没有任何消息。
我有点迷失方向,因为我遵循了所有我找到的教程,但使用完全相同的代码时它就无法正常工作。
这是我在客户端中使用的AngularJS代码:
  var source = new EventSource('/api/payments/listen');

  source.addEventListener('open', function(e) {
    console.log('CONNECTION ESTABLISHED');
  }, false);

  source.addEventListener('message', function (e) {

    $scope.$apply(function () {
      console.log('NOTIFICATION');
      console.log(e.data);
    });

  }, false);

  source.onmessage = function (e) {
    console.log('NOTIFICATION!');
    console.log(e);
  };

  source.addEventListener('error', function(e) {
    if (e.readyState === EventSource.CLOSED) {
      console.log('CONNECTION CLOSED');
    }
  }, false);

服务器端代码:

exports.listen = function (req, res) {

  if (req.headers.accept && req.headers.accept === 'text/event-stream') {

    if ( req.url === '/api/payments/listen' ) {
      sendSSE(req, res);
    }
    else {
     res.writeHead(404);
     res.end();
    }

  }
  else
    res.end();

};

function sendSSE(req, res) {

  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });

  var id = (new Date()).toLocaleTimeString();

  // Sends a SSE every 5 seconds on a single connection.
  setInterval(function() {
    constructSSE(res, id, data);
  }, 5000);

  constructSSE(res, id, data);
}

function constructSSE(res, id, data) {

  res.write('id: ' + id + '\n');
  res.write('data: ' + JSON.stringify(data) + '\n\n');

}

有什么建议?有什么提示吗?

编辑

我不知道是什么原因导致了问题,但是我已经使用了Simple-SSE,这是一个非常有用的小型服务器端事件库,现在它已经按照预期工作。

以下是想要尝试的人的链接: https://github.com/Lesterpig/simple-sse

谢谢 =)


在PHP中,您可以使用带有“sleep”的无限while循环,否则线程将关闭。也许是一样的吗? - Emil S. Jørgensen
你将服务器端事件发送到哪里了?我没有看到任何被调用的事件,我只看到许多客户端监听器,没有来自服务器的发出。 - mattdevio
@EmilS.Jørgensen 我会去查看,但我找到的所有实现示例都没有使用类似的东西。此外,在与服务器建立连接后,我没有在客户端看到任何“连接已关闭”的消息。谢谢! - Rubén Jiménez
@magreenberg据说这是一个流,所以你在管道中写入一些内容,内容直接发送到客户端。 在这种情况下,可以通过“res.write”来实现。无论如何,我也会检查它。 - Rubén Jiménez
你尝试过使用curl调用/api/payments/listen吗?它的行为是否符合你的预期? - baynezy
@baynezy 看起来是这样的。无论如何,我找到了一个“解决方案”。主贴已编辑,解释了我是如何解决这个问题的。谢谢=) - Rubén Jiménez
1个回答

17
希望这对于遇到和我一样问题的人有所帮助。我来到这个问题后,虽然代码中似乎一切正常,但我无法从服务器接收消息。在看到这个库有所帮助后,我深入研究了源代码并找到了答案。如果你像我一样在express应用程序中使用任何压缩库,你需要在写完后刷新响应。否则,压缩不会按照协议预期发送消息。例如: res.write("data:hi\n\n") res.flush()

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