@wiz-develop/server-clock
Version:
Server-synchronized clock implementation for browsers with WebWorker support
2 lines (1 loc) • 8.83 kB
JavaScript
var t,e;t=this,e=function(t){"use strict";function e(t,e,n,i){return new(n||(n=Promise))((function(s,r){function o(t){try{u(i.next(t))}catch(t){r(t)}}function a(t){try{u(i.throw(t))}catch(t){r(t)}}function u(t){var e;t.done?s(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(o,a)}u((i=i.apply(t,e||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const n=t=>`${t.getUTCFullYear()}/${(""+(t.getUTCMonth()+1)).padStart(2,"0")}/${(""+t.getUTCDate()).padStart(2,"0")} ${(""+t.getUTCHours()).padStart(2,"0")}:${(""+t.getUTCMinutes()).padStart(2,"0")}:${(""+t.getUTCSeconds()).padStart(2,"0")}.${(""+t.getUTCMilliseconds()).padStart(3,"0")}`,i=(t,n,i)=>e(void 0,void 0,void 0,(function*(){return"undefined"!=typeof navigator&&!navigator.onLine&&i?i:((t,e)=>{if(0===t.length)return{status:"client_only",offset:0};const{maxLb:n,minUb:i}=t.reduce(((t,e)=>({maxLb:Math.max(t.maxLb,e.lb),minUb:Math.min(t.minUb,e.ub)})),{maxLb:-1/0,minUb:1/0}),s=-(n+i)/2;return t.length>=e.length&&i>n&&500>i-n?{status:"accurate",offset:s}:{status:"server_only",offset:s}})((yield Promise.allSettled(t.map((t=>e(void 0,void 0,void 0,(function*(){const i=Date.now(),s=yield((t,...n)=>e(void 0,[t,...n],void 0,(function*(t,e=3e3){return Promise.race([fetch(t,{method:"GET"}),new Promise(((t,n)=>{setTimeout((()=>{n(Error("\u274c fetch timeout"))}),e)}))])})))(t,n).catch((t=>{throw t})),r=Date.now(),o=yield s.json();if("object"!=typeof(a=o)||null===a||!("requestReceivedAt"in a)||!("responseSentAt"in a)||null==a.requestReceivedAt||null==a.responseSentAt||"number"!=typeof a.requestReceivedAt||"number"!=typeof a.responseSentAt)throw Error(`Invalid server response from '${t}'`);var a;return((t,e,n)=>{const i=n.requestReceivedAt,s=n.responseSentAt;return Object.assign(Object.assign({},n),{it:t,rt:e,rtt:e-t,diff:(i-t-(e-s))/2,lb:t-16-i,ub:e+16-s})})(i,r,o)})))))).filter((t=>"fulfilled"===t.status)).map((t=>t.value)),t)})),s=18e4;class r{constructor(t){var e,n,i,r;this.result={status:"pending",offset:0},this.clockloopTimer=null,this.fetchloopTimer=null,this.tickHandlers=new Set,this.serverUrls=t.serverUrls,this.fetchInterval=null!==(e=t.fetchInterval)&&void 0!==e?e:s,this.clockInterval=null!==(n=t.clockInterval)&&void 0!==n?n:100,this.fetchTimeout=null!==(i=t.fetchTimeout)&&void 0!==i?i:3e3,this.fallbackToLocal=null===(r=t.fallbackToLocal)||void 0===r||r}onTick(t){return this.tickHandlers.add(t),()=>{this.tickHandlers.delete(t)}}start(){return e(this,void 0,void 0,(function*(){this.stop();try{this.result=yield i(this.serverUrls,this.fetchTimeout,this.fallbackToLocal?void 0:this.result)}catch(t){if(!this.fallbackToLocal)throw t}this.fetchloopTimer=setInterval((()=>e(this,void 0,void 0,(function*(){try{this.result=yield i(this.serverUrls,this.fetchTimeout,this.result)}catch(t){}}))),this.fetchInterval),this.clockloopTimer=setInterval((()=>{const t=((t,e)=>{const i=new Date,s=6e4*i.getTimezoneOffset(),r=i.getTime()+t.offset+e/2,o={status:t.status,offset:Math.round(t.offset/1e3*10)/10,LOCAL:new Date(i.getTime()-s),JST:new Date(r+324e5),UTC:new Date(r),LOC:new Date(r-s)};return Object.assign(Object.assign({},o),{LOCAL_STR:n(o.LOCAL),JST_STR:n(o.JST),UTC_STR:n(o.UTC),LOC_STR:n(o.LOC)})})(this.result,this.clockInterval);this.tickHandlers.forEach((e=>{try{e(t)}catch(t){}}))}),this.clockInterval)}))}stop(){this.clockloopTimer&&(clearInterval(this.clockloopTimer),this.clockloopTimer=null),this.fetchloopTimer&&(clearInterval(this.fetchloopTimer),this.fetchloopTimer=null)}}class o{constructor(t,e="./worker.js"){this.worker=null,this.tickHandlers=new Set,this.handleWorkerMessage=t=>{this.tickHandlers.forEach((e=>{try{e(t.data)}catch(t){}}))},this.options=t,this.workerUrl=((t="./worker.js")=>"undefined"==typeof window?t:(()=>{const t=new Blob(['!(function(){"use strict";function e(e,t,n,r){return new(n||(n=Promise))((function(o,i){function s(e){try{a(r.next(e))}catch(e){i(e)}}function u(e){try{a(r.throw(e))}catch(e){i(e)}}function a(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,u)}a((r=r.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const t=e=>`${e.getUTCFullYear()}/${(""+(e.getUTCMonth()+1)).padStart(2,"0")}/${(""+e.getUTCDate()).padStart(2,"0")} ${(""+e.getUTCHours()).padStart(2,"0")}:${(""+e.getUTCMinutes()).padStart(2,"0")}:${(""+e.getUTCSeconds()).padStart(2,"0")}.${(""+e.getUTCMilliseconds()).padStart(3,"0")}`,n=(t,n,r)=>e(void 0,void 0,void 0,(function*(){return"undefined"!=typeof navigator&&!navigator.onLine&&r?r:((e,t)=>{if(0===e.length)return{status:"client_only",offset:0};const{maxLb:n,minUb:r}=e.reduce(((e,t)=>({maxLb:Math.max(e.maxLb,t.lb),minUb:Math.min(e.minUb,t.ub)})),{maxLb:-1/0,minUb:1/0}),o=-(n+r)/2;return e.length>=t.length&&r>n&&500>r-n?{status:"accurate",offset:o}:{status:"server_only",offset:o}})((yield Promise.allSettled(t.map((t=>e(void 0,void 0,void 0,(function*(){const r=Date.now(),o=yield((t,...n)=>e(void 0,[t,...n],void 0,(function*(e,t=3e3){return Promise.race([fetch(e,{method:"GET"}),new Promise(((e,n)=>{setTimeout((()=>{n(Error("\\u274c fetch timeout"))}),t)}))])})))(t,n).catch((e=>{throw e})),i=Date.now(),s=yield o.json();if("object"!=typeof(u=s)||null===u||!("requestReceivedAt"in u)||!("responseSentAt"in u)||null==u.requestReceivedAt||null==u.responseSentAt||"number"!=typeof u.requestReceivedAt||"number"!=typeof u.responseSentAt)throw Error(`Invalid server response from \'${t}\'`);var u;return((e,t,n)=>{const r=n.requestReceivedAt,o=n.responseSentAt;return Object.assign(Object.assign({},n),{it:e,rt:t,rtt:t-e,diff:(r-e-(t-o))/2,lb:e-16-r,ub:t+16-o})})(r,i,s)})))))).filter((e=>"fulfilled"===e.status)).map((e=>e.value)),t)}));if(void 0===self)throw new TypeError("This script must be executed in a WebWorker environment");let r={status:"pending",offset:0},o=null,i=null;self.addEventListener("message",(s=>e(void 0,void 0,void 0,(function*(){switch(s.data.type){case"start":if(null==s.data.serverUrls)break;yield((s,...u)=>e(void 0,[s,...u],void 0,(function*(s,u=18e4){o&&clearInterval(o),i&&clearInterval(i),r=yield n(s,3e3),i=setInterval((()=>e(void 0,void 0,void 0,(function*(){r=yield n(s,3e3,r)}))),u),o=setInterval((()=>{const e=(e=>{const n=new Date,r=6e4*n.getTimezoneOffset(),o=n.getTime()+e.offset+50,i={status:e.status,offset:Math.round(e.offset/1e3*10)/10,LOCAL:new Date(n.getTime()-r),JST:new Date(o+324e5),UTC:new Date(o),LOC:new Date(o-r)};return Object.assign(Object.assign({},i),{LOCAL_STR:t(i.LOCAL),JST_STR:t(i.JST),UTC_STR:t(i.UTC),LOC_STR:t(i.LOC)})})(r);self.postMessage(e)}),100)})))(s.data.serverUrls,s.data.fetchInterval);break;case"stop":o&&(clearInterval(o),o=null),i&&(clearInterval(i),i=null)}})))),self.addEventListener("error",(e=>{}))})();\n'],{type:"application/javascript"});return URL.createObjectURL(t)})())(e)}onTick(t){return this.tickHandlers.add(t),()=>{this.tickHandlers.delete(t)}}start(){this.worker&&this.stop();try{this.worker=new Worker(this.workerUrl),this.worker.addEventListener("message",this.handleWorkerMessage),this.worker.addEventListener("error",o.handleWorkerError),this.worker.postMessage({type:"start",serverUrls:this.options.serverUrls,fetchInterval:this.options.fetchInterval})}catch(t){throw t}}stop(){this.worker&&(this.worker.postMessage({type:"stop"}),this.worker.removeEventListener("message",this.handleWorkerMessage),this.worker.removeEventListener("error",o.handleWorkerError),this.worker.terminate(),this.worker=null)}}o.handleWorkerError=t=>{};class a{constructor(t,e="./worker.js"){var n,i,u,l;this.lastTickData=null,this.tickHandlers=new Set,this.handleTick=t=>{this.lastTickData=t,this.tickHandlers.forEach((e=>{try{e(t)}catch(t){}}))},this.options=Object.assign(Object.assign({},t),{fetchInterval:null!==(n=t.fetchInterval)&&void 0!==n?n:s,clockInterval:null!==(i=t.clockInterval)&&void 0!==i?i:100,fetchTimeout:null!==(u=t.fetchTimeout)&&void 0!==u?u:3e3,fallbackToLocal:null===(l=t.fallbackToLocal)||void 0===l||l}),this.implementation=a.isWorkerAvailable()?new o(this.options,e):new r(this.options),this.implementation.onTick(this.handleTick)}onTick(t){if(this.tickHandlers.add(t),this.lastTickData)try{t(this.lastTickData)}catch(t){}return()=>{this.tickHandlers.delete(t)}}start(){return e(this,void 0,void 0,(function*(){a.isWorkerAvailable()?this.implementation.start():yield this.implementation.start()}))}stop(){this.implementation.stop()}static isWorkerAvailable(){return"undefined"!=typeof Worker&&"file:"!==window.location.protocol}isUsingWorker(){return this.implementation instanceof o}}t.ServerClock=a,t.default=a,Object.defineProperty(t,"t",{value:!0})},"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).WizDevelopServerClock={});