|
|
|
|
|
by efortis
433 days ago
|
|
You can also use long polling, which keeps alive a connection so the server can respond immediately when there’s new data. For example: Server const LONG_POLL_SERVER_TIMEOUT = 8_000
function longPollHandler(req, response) {
// e.g. client can be out of sync if the browser tab was hidden while a new event was triggered
const clientIsOutOfSync = parseInt(req.headers.last_received_event, 10) !== myEvents.count
if (clientIsOutOfSync) {
sendJSON(response, myEvents.count)
return
}
function onMyEvent() {
myEvents.unsubscribe(onMyEvent)
sendJSON(response, myEvents.count)
}
response.setTimeout(LONG_POLL_SERVER_TIMEOUT, onMyEvent)
req.on('error', () => {
myEvents.unsubscribe(onMyEvent)
response.destroy()
})
myEvents.subscribe(onMyEvent)
}
Client (polls when tab is visible) pollMyEvents()
document.addEventListener('visibilitychange', () => {
if (!document.hidden)
pollMyEvents()
})
pollMyEvents.isPolling = false
pollMyEvents.oldCount = 0
async function pollMyEvents() {
if (pollMyEvents.isPolling || document.hidden)
return
try {
pollMyEvents.isPolling = true
const response = await fetch('/api/my-events', {
signal: AbortSignal.timeout(LONG_POLL_SERVER_TIMEOUT + 1000),
headers: { last_received_event: pollMyEvents.oldCount }
})
if (response.ok) {
const nMyEvents = await response.json()
if (pollMyEvents.oldCount !== nMyEvents) { // because it could be < or >
pollMyEvents.oldCount = nMyEvents
setUIState('eventsCount', nMyEvents)
}
pollMyEvents.isPolling = false
pollMyEvents()
}
else
throw response.status
}
catch (_) {
pollMyEvents.isPolling = false
setTimeout(pollMyEvents, 5000)
}
}
Working example at Mockaton:
https://github.com/ericfortis/mockaton/blob/6b7f8eb5fe9d3baf... |
|