StackOverflow utilizes websockets for maintaining a continuous connection between the client and the server, enabling data to be pushed from the server to the client. This method is more efficient than AJAX polling, where data needs to be pulled via AJAX requests. It is likely that StackOverflow reverts to the traditional AJAX polling approach for older browsers lacking support for web sockets.
According to an article on pusher.com:
WebSockets signify a significant advancement in client/server web technology. They facilitate the establishment of a long-lasting single TCP socket connection between the client and server, allowing instant bi-directional communication with minimal overhead and remarkably low latency.
This StackOverflow post effectively outlines the advantages and disadvantages of various client-server communication methods.
The actual implementation code appears as follows:
StackExchange.realtime = function() {
function Socket(options) {
var array = options.split(",");
var length = array.length;
var i = index % length;
var url = array[i];
if (null != url && (0 != url.indexOf("ws://") && (0 != url.indexOf("wss://") && (url = ("https:" === document.location.protocol ? "wss://" : "ws://") + url))), "WebSocket" in window || "MozWebSocket" in window) {
if (self) {
try {
publish("closing WebSocket");
self.close();
} catch (c) {
}
}
if (!self) {
try {
self = "WebSocket" in window ? new WebSocket(url) : new MozWebSocket(url);
} catch (ex) {
return publish("Sockets disabled - " + ex.message), void 0;
}
self.onopen = function() {
if (!U) {
U = true;
}
index = 0;
publish("WebSocket opened");
f();
handle();
setInterval(done, 6E4);
};
self.onmessage = function(msg) {
var self = $.parseJSON(msg.data);
mockPlugin.emitEvent(self.action, [self.data]);
};
self.onclose = function() {
self = null;
publish("WebSocket closed");
if (5 > index) {
if (D > 0) {
index++;
D--;
publish("reconnect attempt:" + index + " max retries:" + D);
setTimeout(function() {
StackExchange.realtime.init(options);
}, (new Date).getTime() % 50 / 20 * 1E3);
}
}
};
self.onerror = function() {
publish("WebSocket failed");
self = null;
};
}
}
}
function f() {
if (null != self && 1 == self.readyState) {
var i = 0;
var l = elems.length;
for (;l > i;i++) {
publish("sending " + elems[i]);
self.send(elems[i]);
}
}
}
function publish(topic) {
if (StackExchange.options.enableLogging) {
console.log("realtime: " + topic);
}
}
function handle() {
mockPlugin.addListener("hb", function(str) {
self.send(str);
});
}
function next(elm) {
elems.push(elm);
f();
}
function callback(i) {
publish("unsubscribing " + i);
var position = $.inArray(i, elems);
if (-1 != position) {
elems.splice(position, 1);
if (null != self) {
if (1 == self.readyState) {
self.send("-" + i);
}
}
}
}
and it is invoked with:
StackExchange.ready(function () {
StackExchange.realtime.init('wss://qa.sockets.stackexchange.com,ws://qa.sockets.stackexchange.com');
StackExchange.realtime.subscribeToInboxNotifications();
StackExchange.realtime.subscribeToReputationNotifications('1');
StackExchange.realtime.subscribeToTopBarNotifications('1');
});