Hacker News new | ask | show | jobs
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...
1 comments

Yep, have used long polling with no downsides for ~20 years. 95% of the time I see web sockets it's unnecessary.