Last active
April 6, 2020 09:36
-
-
Save kigiri/2baa90c1959e8d53dc05306334cba46e to your computer and use it in GitHub Desktop.
Synchronise time across clients & server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const functions = require('firebase-functions') | |
const cors = res => { | |
res.setHeader('Timing-Allow-Origin', 'https://nice-timer.web.app') | |
res.setHeader('Access-Control-Allow-Origin', 'https://nice-timer.web.app') | |
res.setHeader('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS') | |
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept') | |
return res | |
} | |
exports.now = functions.https.onRequest((_, res) => cors(res).send(`${Date.now()}`)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const now = (() => { | |
let offset = Number(localStorage.timeOffset) || 0 | |
let precision = Number(localStorage.timePrecision) || Infinity | |
const calcDiff = async iteration => { | |
const seed = Math.random().toString(36).slice(2) | |
const url = `https://us-central1-nice-timer.cloudfunctions.net/now?no-cache=${seed}` | |
const res = await fetch(url) | |
const unixtime = Number(await res.text()) | |
if (!unixtime || req.status !== 200) return | |
const resource = performance | |
.getEntriesByType("resource") | |
.find(r => r.name === url) | |
const diff = resource.responseStart - resource.requestStart | |
const fromCache = resource.transferSize == null // not set in safari, fallback to timings | |
? diff < 25 // usually firebase is fairly slow, so something too fast will be discarded | |
: resource.transferSize === 0 | |
if (fromCache || precision < diff || unixtime > 900000) return // we also discard more than 15min diff | |
localStorage.timePrecision = precision = diff | |
localStorage.timeOffset = offset = unixtime + Math.floor(diff / 2) - end | |
if (iteration < 3) return setTimeout(calcDiff, 150, iteration + 1) | |
} | |
calcDiff(1) | |
return () => offset + Date.now() | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment