113 lines
2.6 KiB
JavaScript
113 lines
2.6 KiB
JavaScript
/* eslint-env worker */
|
||
'use strict'
|
||
|
||
let eventsPath = null
|
||
let port = null
|
||
let currentVersionId = null
|
||
let eventSource = null
|
||
|
||
addEventListener('connect', (event) => {
|
||
// Only keep one active port, for whichever tab was last loaded.
|
||
if (port) {
|
||
port.close()
|
||
}
|
||
port = event.ports[0]
|
||
port.addEventListener('message', receiveMessage)
|
||
port.start()
|
||
})
|
||
|
||
const receiveMessage = (event) => {
|
||
if (event.data.type === 'initialize') {
|
||
const givenEventsPath = event.data.eventsPath
|
||
|
||
if (givenEventsPath !== eventsPath) {
|
||
if (eventSource) {
|
||
eventSource.close()
|
||
}
|
||
|
||
resetConnectTimeout()
|
||
|
||
setTimeout(connectToEvents, 0)
|
||
}
|
||
|
||
eventsPath = event.data.eventsPath
|
||
}
|
||
}
|
||
|
||
let connectAttempts
|
||
let connectTimeoutMs
|
||
|
||
const resetConnectTimeout = () => {
|
||
connectAttempts = 0
|
||
connectTimeoutMs = 100
|
||
}
|
||
resetConnectTimeout()
|
||
|
||
const bumpConnectTimeout = () => {
|
||
connectAttempts++
|
||
|
||
if (connectTimeoutMs === 100 && connectAttempts === 20) {
|
||
connectAttempts = 0
|
||
connectTimeoutMs = 300
|
||
} else if (connectTimeoutMs === 300 && connectAttempts === 20) {
|
||
connectAttempts = 0
|
||
connectTimeoutMs = 1000
|
||
} else if (connectTimeoutMs === 1000 && connectAttempts === 20) {
|
||
connectAttempts = 0
|
||
connectTimeoutMs = 3000
|
||
} else if (connectAttempts === 100) {
|
||
// Give up after 5 minutes.
|
||
console.debug(
|
||
'😢 django-browser-reload failed to connect after 5 minutes, shutting down.'
|
||
)
|
||
close()
|
||
return
|
||
}
|
||
if (connectAttempts === 0) {
|
||
console.debug(
|
||
'😅 django-browser-reload EventSource error, retrying every ' +
|
||
connectTimeoutMs +
|
||
'ms'
|
||
)
|
||
}
|
||
}
|
||
|
||
const connectToEvents = () => {
|
||
if (!eventsPath) {
|
||
setTimeout(connectToEvents, connectTimeoutMs)
|
||
return
|
||
}
|
||
|
||
eventSource = new EventSource(eventsPath)
|
||
|
||
eventSource.addEventListener('open', () => {
|
||
console.debug('😎 django-browser-reload connected')
|
||
})
|
||
|
||
eventSource.addEventListener('message', (event) => {
|
||
// Reset connection timeout when receiving a message, as it’s proof that
|
||
// we are actually connected.
|
||
resetConnectTimeout()
|
||
|
||
const message = JSON.parse(event.data)
|
||
|
||
if (message.type === 'ping') {
|
||
if (currentVersionId !== null && currentVersionId !== message.versionId) {
|
||
console.debug('🔁 django-browser-reload triggering reload.')
|
||
port.postMessage('Reload')
|
||
}
|
||
|
||
currentVersionId = message.versionId
|
||
} else if (message.type === 'reload') {
|
||
port.postMessage('Reload')
|
||
}
|
||
})
|
||
|
||
eventSource.addEventListener('error', () => {
|
||
eventSource.close()
|
||
eventSource = null
|
||
bumpConnectTimeout()
|
||
setTimeout(connectToEvents, connectTimeoutMs)
|
||
})
|
||
}
|