I am seeing odd behavior with the code here.
Client-side (Javascript):
<input type="text" id="userid" placeholder="UserID" /><br />`
<input type="button" id="ping" value="Ping" />
<script>
var es = new EventSource('/home/message');
es.onmessage = function (e) {
console.log(e.data);
};
es.onerror = function () {
console.log(arguments);
};
$(function () {
$('#ping').on('click', function () {
$.post('/home/ping', {
UserID: parseInt($('#userid').val()) || 0
});
});
});
</script>
Server-side (C#):
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Web.Mvc;
using Newtonsoft.Json;
namespace EventSourceTest2.Controllers {
public class PingData {
public int UserID { get; set; }
public DateTime Date { get; set; } = DateTime.Now;
}
public class HomeController : Controller {
public ActionResult Index() {
return View();
}
static ConcurrentQueue<PingData> pings = new ConcurrentQueue<PingData>();
public void Ping(int userID) {
pings.Enqueue(new PingData { UserID = userID });
}
public void Message() {
Response.ContentType = "text/event-stream";
do {
PingData nextPing;
if (pings.TryDequeue(out nextPing)) {
var msg = "data:" + JsonConvert.SerializeObject(nextPing, Formatting.None) + "\n\n";
Response.Write(msg);
}
Response.Flush();
Thread.Sleep(1000);
} while (true);
}
}
}
Once I've pressed ping to add a new item to the pings
queue, the loop inside the Message
method picks the new item up and issues an event, via Response.Write
(confirmed using Debug.Print on the server). However, the browser doesn't trigger onmessage
until I press ping a second time, and the browser issues another event; at which point the data from the first event reaches onmessage
.
How can I fix this?
To clarify, this is the behavior I would expect:
Client Server
-------------------------------------------------------------------
Press Ping button
XHR to /home/ping
Eneque new item to pings
Message loop issues server-sent event
EventSource calls onmessage
This is what is actually happening:
Client Server
-------------------------------------------------------------------
Press Ping button
XHR to /home/ping
Eneque new item to pings
Message loop issues server-sent event
(Nothing happens)
Press Ping button again
New XHR to /home/ping
EventSource calls onmessage with previous event data
(While running in Chrome the message
request is listed in the Network tab as always pending. I'm not sure if this is the normal behavior of server-sent events, or perhaps it's related to the issue.)
Edit
The string representation of the msg
variable after Response.Write
looks like this:
"data:{\"UserID\":105,\"Date\":\"2016-03-11T04:20:24.1854996+02:00\"}\n\n"
very clearly including the newlines.