eventsource icon indicating copy to clipboard operation
eventsource copied to clipboard

Messages are delayed in IE 11

Open christophercr opened this issue 7 years ago • 6 comments

Hi, I'm trying to use this library with IE 11 but I get a weird behaviour: the messages are delayed and they are received by the client all at once after a certain period of time (around 2 minutes!). To test this I have a simple server in Express that emits messages every 2 secs.

In my express server, the headers I set are these:

// set timeout as high as possible
req.socket.setTimeout(0);

// send headers for event-stream connection
// see spec for more information
resp.writeHead(200, {
	'Content-Type': 'text/event-stream',
	'Cache-Control': 'no-cache',
	'Connection': 'keep-alive',
	'Access-Control-Allow-Origin': '*'
});
resp.write('\n');

The messages are created like this:

var d = new Date();
resp.write('id: ' + d.getMilliseconds() + '\n');
resp.write('event:' + 'message') + '\n');
resp.write('data:' + createMsg(d) + '\n\n'); // Note the extra newline

Finally, in the client I use it as suggested:

let eventSource = new EventSource("http://localhost:4000/sse");
eventSource.addEventListener("message", (event) => console.log("message received:", event), false);
eventSource.addEventListener("open", (event) => console.log("onopen:", event), false);
eventSource.addEventListener("error", (event) => console.log("onerror:", event), false);

As I said, the messages are delayed in IE 11 and they arrive all together after 2 mins aprox.

However, if I use this other EventSource polyfill which is a fork of Yaffle/EventSource, IE11 receives the messages immediately as soon as the server sends them.

I'm wondering if your polyfill is supposed to work in IE11 or is not supported? If it is supported, do you happen to know what the issue could be?

christophercr avatar Sep 21 '17 13:09 christophercr

I can't speak for why the other polyfills work, but it's recommended that you send back a 2056 character comment at the start of the stream in the case of internet explorer. Try this at the start of each connect:

resp.write(new Array(2057).join(':') + '\n\n')

rexxars avatar Sep 21 '17 13:09 rexxars

@rexxars that's certainly a workaround, but it doesn't explain why the other polyfills work without this server hack.

When Webpack (or Browserify) builds the polyfill, it replaces all of the node http code with https://github.com/jhiesey/stream-http. That library uses XMLHttpRequest just like the other polyfills, so there must be a difference in how they're using it.

aslakhellesoy avatar Sep 21 '17 14:09 aslakhellesoy

I've applied the workaround that @rexxars suggested, and strangely enough, IE receives the messages more frequently but they are delayed still, now the messages are received in a period where 2 or 3 messages are sent.

This is what I do now in the server:

var d = new Date();
resp.write(new Array(2057).join(':') + '\n'); // padding for IE
resp.write('id: ' + d.getMilliseconds() + '\n');
resp.write('event:' + 'message' + '\n');
resp.write('data:' + createMsg(d) + '\n\n'); // Note the extra newline

I also tried to do it only in every new connection:

resp.writeHead(200, {
  ... // the headers
});
resp.write(new Array(2057).join(':') + '\n'); // padding for IE

but the last one did not work, still the delay of about 2 mins

christophercr avatar Sep 21 '17 14:09 christophercr

I wouldn't trust any server side hacks to make this work. There is a bug in the code that needs to be fixed, period.

aslakhellesoy avatar Sep 21 '17 15:09 aslakhellesoy

Any news on a fix?

bastijns-jeroen avatar Jun 04 '18 12:06 bastijns-jeroen

The "server side hack" is also present on other polyfills. I wonder if the issue is the id: d.getMilliseconds() that would return the same id since it only gives the the current number of milliseconds (from 0 to 999) for the current second. So, it'd be much better to use a increasing unique identifier.

Both IE and Edge buffers the data from the network layer, and that's why you need the padding hack, so the JS callback are called when the buffer is full. If the id fix above doesn't work, I wonder if you should make your event larger so the buffer hits the JS's callback. Typically, it's likely the AJAX connection underneath (in the polyfill implementation) times out, and tries to reconnect. In that case, you'd need to pad the connection again. That's a real PITA, but since it's bug in the browser, there nothing you can do against.

Please notice that IE/Edge's polyfill emulate a streaming connection with a non-streaming based technology. So it reconnects much more frequently (you can increase the timeout on the browser's library).

X-Ryl669 avatar Jan 07 '19 15:01 X-Ryl669