7

I'm using MEAN and I'm trying to receive events from server side. For that, Im using EventSource but It just doesn't work.

I see how connection is open but I don't get any message from server. I can see in Node console how the messages are being sent but in client side there's nothing (browser console).

I'm a bit lost as I'm following all the tutorials I've found, but using exactly the same code it just doesn't work.

In client side, this is my AngularJS code:

  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);

Server side code:

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');

}

Any suggestion? Any tip?

Edit

I don't know what was causing the issue, but I have got it to work using Simple-SSE, a useful and little library for server side events.

Now, it is working as expected.

Here it is the link for those who wants to give it a try: https://github.com/Lesterpig/simple-sse

Thanks =)

Rubén Jiménez
  • 1,835
  • 5
  • 21
  • 29
  • In PHP you would use an infinite while loop with `sleep`, because otherwise the thread will close. Maybe it's the same? – Emil S. Jørgensen Oct 28 '16 at 12:36
  • Where are you sending the server side event? I don't see an event being called, I see a lot of client side listeners, no emit from server. – mattdevio Oct 28 '16 at 14:20
  • @EmilS.Jørgensen I'll check it out but none of the implementation examples I've found use something like that. Besides, I don't see any "CONNECTION CLOSED" in client side after connection is established with server. Thanks! – Rubén Jiménez Oct 28 '16 at 21:44
  • @magreenberg It is supposedly a stream so you write something in the pipe and the content goes directly to client side. In this case, that is accomplished by "res.write". Anyway, I'll check it out as well. – Rubén Jiménez Oct 28 '16 at 21:44
  • Have tried calling /api/payments/listen with curl? Does it behave as you would expect? – baynezy Oct 30 '16 at 09:18
  • @baynezy Apparently it does. Anyway, I found a "solution". Main post is edited explaining how I solved the issue. Thanks =) – Rubén Jiménez Oct 31 '16 at 12:27

1 Answers1

17

Hope this helps anyone that was having the same issue I was. I came to this question, after not being able to receive messages from the server although everything in my code seemed to be exactly how it was supposed to. After seeing that this library helped I dug into source code and found my answer. If you are using any compression library such as I was in my express app, you need to flush the response after the write. other wise the compression doesn't send the message as the protocol expects. e.g. res.write("data:hi\n\n") res.flush()

Jay Garzon
  • 236
  • 2
  • 7