46 lines
2.0 KiB
JavaScript
46 lines
2.0 KiB
JavaScript
// Network-only recovery entry: older workers do not intercept this page.
|
|
const button = document.querySelector('#update');
|
|
const status = document.querySelector('#status');
|
|
function waitForState(worker, states) {
|
|
return new Promise((resolve, reject) => {
|
|
const finish = error => {
|
|
clearTimeout(timer);
|
|
worker.removeEventListener('statechange', check);
|
|
error ? reject(error) : resolve();
|
|
};
|
|
const check = () => {
|
|
if (states.includes(worker.state)) finish();
|
|
else if (worker.state === 'redundant') finish(new Error('download'));
|
|
};
|
|
const timer = setTimeout(() => finish(new Error('timeout')), 120000);
|
|
worker.addEventListener('statechange', check);
|
|
check();
|
|
});
|
|
}
|
|
button.addEventListener('click', async () => {
|
|
button.disabled = true;
|
|
status.textContent = '正在检查并下载完整资源,请保持联网…';
|
|
try {
|
|
if (!window.isSecureContext || !('serviceWorker' in navigator)) throw new Error('unsupported');
|
|
const base = new URL('./', location.href);
|
|
const registration = await navigator.serviceWorker.register(new URL('sw.js', base), {scope: base.href, updateViaCache: 'none'});
|
|
// Await the network check even if a previous waiting version already exists.
|
|
await registration.update();
|
|
const installing = registration.installing;
|
|
if (installing) await waitForState(installing, ['installed', 'activating', 'activated']);
|
|
const worker = registration.waiting || registration.active;
|
|
if (!worker) throw new Error('download');
|
|
if (registration.waiting) {
|
|
status.textContent = '资源已就绪,正在应用更新…';
|
|
worker.postMessage({type: 'RHINE_APPLY_UPDATE'});
|
|
}
|
|
await waitForState(worker, ['activated']);
|
|
// Claiming clients is part of the worker's activation; navigate afterwards.
|
|
location.replace(base.href);
|
|
} catch {
|
|
status.textContent = '更新未完成,已保留原有数据。请确认网络可用后重试。';
|
|
button.textContent = '重试更新 ↻';
|
|
button.disabled = false;
|
|
}
|
|
});
|