UNPKG

timesync

Version:

Time synchronization between peers

1 lines 24.9 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.timesync=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r}()({1:[function(require,module,exports){"use strict";var rawAsap=require("./raw");var freeTasks=[];var pendingErrors=[];var requestErrorThrow=rawAsap.makeRequestCallFromTimer(throwFirstError);function throwFirstError(){if(pendingErrors.length){throw pendingErrors.shift()}}module.exports=asap;function asap(task){var rawTask;if(freeTasks.length){rawTask=freeTasks.pop()}else{rawTask=new RawTask}rawTask.task=task;rawAsap(rawTask)}function RawTask(){this.task=null}RawTask.prototype.call=function(){try{this.task.call()}catch(error){if(asap.onerror){asap.onerror(error)}else{pendingErrors.push(error);requestErrorThrow()}}finally{this.task=null;freeTasks[freeTasks.length]=this}}},{"./raw":2}],2:[function(require,module,exports){"use strict";module.exports=rawAsap;function rawAsap(task){if(!queue.length){requestFlush();flushing=true}queue[queue.length]=task}var queue=[];var flushing=false;var requestFlush;var index=0;var capacity=1024;function flush(){while(index<queue.length){var currentIndex=index;index=index+1;queue[currentIndex].call();if(index>capacity){for(var scan=0,newLength=queue.length-index;scan<newLength;scan++){queue[scan]=queue[scan+index]}queue.length-=index;index=0}}queue.length=0;index=0;flushing=false}var scope=typeof global!=="undefined"?global:self;var BrowserMutationObserver=scope.MutationObserver||scope.WebKitMutationObserver;if(typeof BrowserMutationObserver==="function"){requestFlush=makeRequestCallFromMutationObserver(flush)}else{requestFlush=makeRequestCallFromTimer(flush)}rawAsap.requestFlush=requestFlush;function makeRequestCallFromMutationObserver(callback){var toggle=1;var observer=new BrowserMutationObserver(callback);var node=document.createTextNode("");observer.observe(node,{characterData:true});return function requestCall(){toggle=-toggle;node.data=toggle}}function makeRequestCallFromTimer(callback){return function requestCall(){var timeoutHandle=setTimeout(handleTimer,0);var intervalHandle=setInterval(handleTimer,50);function handleTimer(){clearTimeout(timeoutHandle);clearInterval(intervalHandle);callback()}}}rawAsap.makeRequestCallFromTimer=makeRequestCallFromTimer},{}],3:[function(require,module,exports){"use strict";module.exports=require("./lib")},{"./lib":8}],4:[function(require,module,exports){"use strict";var asap=require("asap/raw");function noop(){}var LAST_ERROR=null;var IS_ERROR={};function getThen(obj){try{return obj.then}catch(ex){LAST_ERROR=ex;return IS_ERROR}}function tryCallOne(fn,a){try{return fn(a)}catch(ex){LAST_ERROR=ex;return IS_ERROR}}function tryCallTwo(fn,a,b){try{fn(a,b)}catch(ex){LAST_ERROR=ex;return IS_ERROR}}module.exports=Promise;function Promise(fn){if(typeof this!=="object"){throw new TypeError("Promises must be constructed via new")}if(typeof fn!=="function"){throw new TypeError("Promise constructor's argument is not a function")}this._1=0;this._2=0;this._3=null;this._4=null;if(fn===noop)return;doResolve(fn,this)}Promise._5=null;Promise._6=null;Promise._7=noop;Promise.prototype.then=function(onFulfilled,onRejected){if(this.constructor!==Promise){return safeThen(this,onFulfilled,onRejected)}var res=new Promise(noop);handle(this,new Handler(onFulfilled,onRejected,res));return res};function safeThen(self,onFulfilled,onRejected){return new self.constructor(function(resolve,reject){var res=new Promise(noop);res.then(resolve,reject);handle(self,new Handler(onFulfilled,onRejected,res))})}function handle(self,deferred){while(self._2===3){self=self._3}if(Promise._5){Promise._5(self)}if(self._2===0){if(self._1===0){self._1=1;self._4=deferred;return}if(self._1===1){self._1=2;self._4=[self._4,deferred];return}self._4.push(deferred);return}handleResolved(self,deferred)}function handleResolved(self,deferred){asap(function(){var cb=self._2===1?deferred.onFulfilled:deferred.onRejected;if(cb===null){if(self._2===1){resolve(deferred.promise,self._3)}else{reject(deferred.promise,self._3)}return}var ret=tryCallOne(cb,self._3);if(ret===IS_ERROR){reject(deferred.promise,LAST_ERROR)}else{resolve(deferred.promise,ret)}})}function resolve(self,newValue){if(newValue===self){return reject(self,new TypeError("A promise cannot be resolved with itself."))}if(newValue&&(typeof newValue==="object"||typeof newValue==="function")){var then=getThen(newValue);if(then===IS_ERROR){return reject(self,LAST_ERROR)}if(then===self.then&&newValue instanceof Promise){self._2=3;self._3=newValue;finale(self);return}else if(typeof then==="function"){doResolve(then.bind(newValue),self);return}}self._2=1;self._3=newValue;finale(self)}function reject(self,newValue){self._2=2;self._3=newValue;if(Promise._6){Promise._6(self,newValue)}finale(self)}function finale(self){if(self._1===1){handle(self,self._4);self._4=null}if(self._1===2){for(var i=0;i<self._4.length;i++){handle(self,self._4[i])}self._4=null}}function Handler(onFulfilled,onRejected,promise){this.onFulfilled=typeof onFulfilled==="function"?onFulfilled:null;this.onRejected=typeof onRejected==="function"?onRejected:null;this.promise=promise}function doResolve(fn,promise){var done=false;var res=tryCallTwo(fn,function(value){if(done)return;done=true;resolve(promise,value)},function(reason){if(done)return;done=true;reject(promise,reason)});if(!done&&res===IS_ERROR){done=true;reject(promise,LAST_ERROR)}}},{"asap/raw":2}],5:[function(require,module,exports){"use strict";var Promise=require("./core.js");module.exports=Promise;Promise.prototype.done=function(onFulfilled,onRejected){var self=arguments.length?this.then.apply(this,arguments):this;self.then(null,function(err){setTimeout(function(){throw err},0)})}},{"./core.js":4}],6:[function(require,module,exports){"use strict";var Promise=require("./core.js");module.exports=Promise;var TRUE=valuePromise(true);var FALSE=valuePromise(false);var NULL=valuePromise(null);var UNDEFINED=valuePromise(undefined);var ZERO=valuePromise(0);var EMPTYSTRING=valuePromise("");function valuePromise(value){var p=new Promise(Promise._7);p._2=1;p._3=value;return p}Promise.resolve=function(value){if(value instanceof Promise)return value;if(value===null)return NULL;if(value===undefined)return UNDEFINED;if(value===true)return TRUE;if(value===false)return FALSE;if(value===0)return ZERO;if(value==="")return EMPTYSTRING;if(typeof value==="object"||typeof value==="function"){try{var then=value.then;if(typeof then==="function"){return new Promise(then.bind(value))}}catch(ex){return new Promise(function(resolve,reject){reject(ex)})}}return valuePromise(value)};var iterableToArray=function(iterable){if(typeof Array.from==="function"){iterableToArray=Array.from;return Array.from(iterable)}iterableToArray=function(x){return Array.prototype.slice.call(x)};return Array.prototype.slice.call(iterable)};Promise.all=function(arr){var args=iterableToArray(arr);return new Promise(function(resolve,reject){if(args.length===0)return resolve([]);var remaining=args.length;function res(i,val){if(val&&(typeof val==="object"||typeof val==="function")){if(val instanceof Promise&&val.then===Promise.prototype.then){while(val._2===3){val=val._3}if(val._2===1)return res(i,val._3);if(val._2===2)reject(val._3);val.then(function(val){res(i,val)},reject);return}else{var then=val.then;if(typeof then==="function"){var p=new Promise(then.bind(val));p.then(function(val){res(i,val)},reject);return}}}args[i]=val;if(--remaining===0){resolve(args)}}for(var i=0;i<args.length;i++){res(i,args[i])}})};function onSettledFulfill(value){return{status:"fulfilled",value:value}}function onSettledReject(reason){return{status:"rejected",reason:reason}}function mapAllSettled(item){if(item&&(typeof item==="object"||typeof item==="function")){if(item instanceof Promise&&item.then===Promise.prototype.then){return item.then(onSettledFulfill,onSettledReject)}var then=item.then;if(typeof then==="function"){return new Promise(then.bind(item)).then(onSettledFulfill,onSettledReject)}}return onSettledFulfill(item)}Promise.allSettled=function(iterable){return Promise.all(iterableToArray(iterable).map(mapAllSettled))};Promise.reject=function(value){return new Promise(function(resolve,reject){reject(value)})};Promise.race=function(values){return new Promise(function(resolve,reject){iterableToArray(values).forEach(function(value){Promise.resolve(value).then(resolve,reject)})})};Promise.prototype["catch"]=function(onRejected){return this.then(null,onRejected)}},{"./core.js":4}],7:[function(require,module,exports){"use strict";var Promise=require("./core.js");module.exports=Promise;Promise.prototype.finally=function(f){return this.then(function(value){return Promise.resolve(f()).then(function(){return value})},function(err){return Promise.resolve(f()).then(function(){throw err})})}},{"./core.js":4}],8:[function(require,module,exports){"use strict";module.exports=require("./core.js");require("./done.js");require("./finally.js");require("./es6-extensions.js");require("./node-extensions.js");require("./synchronous.js")},{"./core.js":4,"./done.js":5,"./es6-extensions.js":6,"./finally.js":7,"./node-extensions.js":9,"./synchronous.js":10}],9:[function(require,module,exports){"use strict";var Promise=require("./core.js");var asap=require("asap");module.exports=Promise;Promise.denodeify=function(fn,argumentCount){if(typeof argumentCount==="number"&&argumentCount!==Infinity){return denodeifyWithCount(fn,argumentCount)}else{return denodeifyWithoutCount(fn)}};var callbackFn="function (err, res) {"+"if (err) { rj(err); } else { rs(res); }"+"}";function denodeifyWithCount(fn,argumentCount){var args=[];for(var i=0;i<argumentCount;i++){args.push("a"+i)}var body=["return function ("+args.join(",")+") {","var self = this;","return new Promise(function (rs, rj) {","var res = fn.call(",["self"].concat(args).concat([callbackFn]).join(","),");","if (res &&",'(typeof res === "object" || typeof res === "function") &&','typeof res.then === "function"',") {rs(res);}","});","};"].join("");return Function(["Promise","fn"],body)(Promise,fn)}function denodeifyWithoutCount(fn){var fnLength=Math.max(fn.length-1,3);var args=[];for(var i=0;i<fnLength;i++){args.push("a"+i)}var body=["return function ("+args.join(",")+") {","var self = this;","var args;","var argLength = arguments.length;","if (arguments.length > "+fnLength+") {","args = new Array(arguments.length + 1);","for (var i = 0; i < arguments.length; i++) {","args[i] = arguments[i];","}","}","return new Promise(function (rs, rj) {","var cb = "+callbackFn+";","var res;","switch (argLength) {",args.concat(["extra"]).map(function(_,index){return"case "+index+":"+"res = fn.call("+["self"].concat(args.slice(0,index)).concat("cb").join(",")+");"+"break;"}).join(""),"default:","args[argLength] = cb;","res = fn.apply(self, args);","}","if (res &&",'(typeof res === "object" || typeof res === "function") &&','typeof res.then === "function"',") {rs(res);}","});","};"].join("");return Function(["Promise","fn"],body)(Promise,fn)}Promise.nodeify=function(fn){return function(){var args=Array.prototype.slice.call(arguments);var callback=typeof args[args.length-1]==="function"?args.pop():null;var ctx=this;try{return fn.apply(this,arguments).nodeify(callback,ctx)}catch(ex){if(callback===null||typeof callback=="undefined"){return new Promise(function(resolve,reject){reject(ex)})}else{asap(function(){callback.call(ctx,ex)})}}}};Promise.prototype.nodeify=function(callback,ctx){if(typeof callback!="function")return this;this.then(function(value){asap(function(){callback.call(ctx,null,value)})},function(err){asap(function(){callback.call(ctx,err)})})}},{"./core.js":4,asap:1}],10:[function(require,module,exports){"use strict";var Promise=require("./core.js");module.exports=Promise;Promise.enableSynchronous=function(){Promise.prototype.isPending=function(){return this.getState()==0};Promise.prototype.isFulfilled=function(){return this.getState()==1};Promise.prototype.isRejected=function(){return this.getState()==2};Promise.prototype.getValue=function(){if(this._2===3){return this._3.getValue()}if(!this.isFulfilled()){throw new Error("Cannot get a value of an unfulfilled promise.")}return this._3};Promise.prototype.getReason=function(){if(this._2===3){return this._3.getReason()}if(!this.isRejected()){throw new Error("Cannot get a rejection reason of a non-rejected promise.")}return this._3};Promise.prototype.getState=function(){if(this._2===3){return this._3.getState()}if(this._2===-1||this._2===-2){return 0}return this._2}};Promise.disableSynchronous=function(){Promise.prototype.isPending=undefined;Promise.prototype.isFulfilled=undefined;Promise.prototype.isRejected=undefined;Promise.prototype.getValue=undefined;Promise.prototype.getReason=undefined;Promise.prototype.getState=undefined}},{"./core.js":4}],11:[function(require,module,exports){"use strict";module.exports=typeof window==="undefined"||typeof window.Promise==="undefined"?require("promise"):window.Promise},{promise:3}],12:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports["default"]=emitter;function emitter(obj){var _callbacks={};obj.emit=function(event,data){var callbacks=_callbacks[event];callbacks&&callbacks.forEach(function(callback){return callback(data)})};obj.on=function(event,callback){var callbacks=_callbacks[event]||(_callbacks[event]=[]);callbacks.push(callback);return obj};obj.off=function(event,callback){if(callback){var callbacks=_callbacks[event];var index=callbacks.indexOf(callback);if(index!==-1){callbacks.splice(index,1)}if(callbacks.length===0){delete _callbacks[event]}}else{delete _callbacks[event]}return obj};obj.list=function(event){return _callbacks[event]||[]};return obj}},{}],13:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.fetch=fetch;exports.post=post;function fetch(method,url,body,headers,callback,timeout){try{var xhr=new XMLHttpRequest;xhr.onreadystatechange=function(){if(xhr.readyState==4){var contentType=xhr.getResponseHeader("Content-Type");if(contentType&&contentType.indexOf("json")!==-1){try{var response=JSON.parse(xhr.responseText);callback(null,response,xhr.status)}catch(err){callback(err,null,xhr.status)}}else{callback(null,xhr.responseText,xhr.status)}}};if(headers){for(var name in headers){if(headers.hasOwnProperty(name)){xhr.setRequestHeader(name,headers[name])}}}xhr.ontimeout=function(err){callback(err,null,0)};xhr.open(method,url,true);xhr.timeout=timeout;if(typeof body==="string"){xhr.send(body)}else if(body){xhr.setRequestHeader("Content-Type","application/json");xhr.send(JSON.stringify(body))}else{xhr.send()}}catch(err){callback(err,null,0)}}function post(url,body,timeout){return new Promise(function(resolve,reject){var callback=function callback(err,res,status){if(err){return reject(err)}resolve([res,status])};fetch("POST",url,body,null,callback,timeout)})}},{}],14:[function(require,module,exports){"use strict";var isBrowser=typeof document!=="undefined";var isReactNative=typeof navigator!=="undefined"&&navigator.product==="ReactNative";module.exports=isBrowser||isReactNative?require("./request.browser"):require("./request.node")},{"./request.browser":13,"./request.node":15}],15:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.post=post;var _http=_interopRequireDefault(require("http"));var _https=_interopRequireDefault(require("https"));var _url=_interopRequireDefault(require("url"));function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}var parseUrl=_url["default"].parse;function post(url,body,timeout){return new Promise(function(resolve,reject){var data=body==="string"?body:JSON.stringify(body);var urlObj=parseUrl(url);var options={host:urlObj.hostname,port:urlObj.port,path:urlObj.path,method:"POST",headers:{"Content-Length":data.length}};if(body!=="string"){options.headers["Content-Type"]="application/json"}var proto=urlObj.protocol==="https:"?_https["default"]:_http["default"];var req=proto.request(options,function(res){res.setEncoding("utf8");var result="";res.on("data",function(data){result+=data});res.on("end",function(){var contentType=res.headers["content-type"];var isJSON=contentType&&contentType.indexOf("json")!==-1;try{var body=isJSON?JSON.parse(result):result;resolve([body,res.statusCode])}catch(err){reject(err)}})});req.on("error",reject);req.on("socket",function(socket){socket.setTimeout(timeout,function(){req.abort()})});req.write(data);req.end()})}},{http:undefined,https:undefined,url:undefined}],16:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.add=add;exports.compare=compare;exports.mean=mean;exports.median=median;exports.std=std;exports.sum=sum;exports.variance=variance;function compare(a,b){return a>b?1:a<b?-1:0}function add(a,b){return a+b}function sum(arr){return arr.reduce(add)}function mean(arr){return sum(arr)/arr.length}function std(arr){return Math.sqrt(variance(arr))}function variance(arr){if(arr.length<2)return 0;var _mean=mean(arr);return arr.map(function(x){return Math.pow(x-_mean,2)}).reduce(add)/(arr.length-1)}function median(arr){if(arr.length<2)return arr[0];var sorted=arr.slice().sort(compare);if(sorted.length%2===0){return(sorted[arr.length/2-1]+sorted[arr.length/2])/2}else{return sorted[(arr.length-1)/2]}}},{}],17:[function(require,module,exports){"use strict";function _typeof(obj){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj},_typeof(obj)}Object.defineProperty(exports,"__esModule",{value:true});exports.create=create;var util=_interopRequireWildcard(require("./util.js"));var stat=_interopRequireWildcard(require("./stat.js"));var request=_interopRequireWildcard(require("./request/request"));var _emitter=_interopRequireDefault(require("./emitter.js"));function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _getRequireWildcardCache(nodeInterop){if(typeof WeakMap!=="function")return null;var cacheBabelInterop=new WeakMap;var cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function _getRequireWildcardCache(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule){return obj}if(obj===null||_typeof(obj)!=="object"&&typeof obj!=="function"){return{default:obj}}var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj)){return cache.get(obj)}var newObj={};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(key!=="default"&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc)}else{newObj[key]=obj[key]}}}newObj["default"]=obj;if(cache){cache.set(obj,newObj)}return newObj}var Promise=require("./Promise");function create(options){var timesync={options:{interval:60*60*1e3,timeout:1e4,delay:1e3,repeat:5,peers:[],server:null,now:Date.now},offset:0,_timeout:null,_inProgress:{},_isFirst:true,send:function send(to,data,timeout){return request.post(to,data,timeout).then(function(val){var res=val[0];if(val[1]!==200){throw new Error("Send failure: bad HTTP StatusCode ("+val[1]+")")}timesync.receive(to,res)})["catch"](function(err){emitError(err)})},receive:function receive(from,data){if(data===undefined){data=from;from=undefined}if(data&&data.id in timesync._inProgress){timesync._inProgress[data.id](data.result)}else if(data&&data.id!==undefined){timesync.send(from,{jsonrpc:"2.0",id:data.id,result:timesync.now()})}},_handleRPCSendError:function _handleRPCSendError(id,reject,err){delete timesync._inProgress[id];reject(new Error("Send failure"))},rpc:function rpc(to,method,params){var id=util.nextId();var resolve,reject;var deferred=new Promise(function(res,rej){resolve=res;reject=rej});timesync._inProgress[id]=function(data){delete timesync._inProgress[id];resolve(data)};var sendResult;try{sendResult=timesync.send(to,{jsonrpc:"2.0",id:id,method:method,params:params},timesync.options.timeout)}catch(err){timesync._handleRPCSendError(id,reject,err)}if(sendResult&&(sendResult instanceof Promise||sendResult.then&&sendResult["catch"])){sendResult["catch"](timesync._handleRPCSendError.bind(this,id,reject))}else{console.warn("Send should return a promise")}return deferred},sync:function sync(){timesync.emit("sync","start");var peers=timesync.options.server?[timesync.options.server]:timesync.options.peers;return Promise.all(peers.map(function(peer){return timesync._syncWithPeer(peer)})).then(function(all){var offsets=all.filter(function(offset){return timesync._validOffset(offset)});if(offsets.length>0){timesync.offset=stat.mean(offsets);timesync.emit("change",timesync.offset)}timesync.emit("sync","end")})},_validOffset:function _validOffset(offset){return offset!==null&&!isNaN(offset)&&isFinite(offset)},_syncWithPeer:function _syncWithPeer(peer){var all=[];function sync(){return timesync._getOffset(peer).then(function(result){return all.push(result)})}function waitAndSync(){return util.wait(timesync.options.delay).then(sync)}function notDone(){return all.length<timesync.options.repeat}return sync().then(function(){return util.whilst(notDone,waitAndSync)}).then(function(){var results=all.filter(function(result){return result!==null});var roundtrips=results.map(function(result){return result.roundtrip});var limit=stat.median(roundtrips)+stat.std(roundtrips);var filtered=results.filter(function(result){return result.roundtrip<limit});var offsets=filtered.map(function(result){return result.offset});return offsets.length>0?stat.mean(offsets):null})},_getOffset:function _getOffset(peer){var start=timesync.options.now();return timesync.rpc(peer,"timesync").then(function(timestamp){var end=timesync.options.now();var roundtrip=end-start;var offset=timestamp-end+roundtrip/2;if(timesync._isFirst){timesync._isFirst=false;timesync.offset=offset;timesync.emit("change",offset)}return{roundtrip:roundtrip,offset:offset}})["catch"](function(err){return null})},now:function now(){return timesync.options.now()+timesync.offset},destroy:function destroy(){clearTimeout(timesync._timeout)}};if(options){if(options.server&&options.peers){throw new Error('Configure either option "peers" or "server", not both.')}for(var prop in options){if(options.hasOwnProperty(prop)){if(prop==="peers"&&typeof options.peers==="string"){timesync.options.peers=options.peers.split(",").map(function(peer){return peer.trim()}).filter(function(peer){return peer!==""})}else{timesync.options[prop]=options[prop]}}}}(0,_emitter["default"])(timesync);function emitError(err){if(timesync.list("error").length>0){timesync.emit("error",err)}else{console.log("Error",err)}}if(timesync.options.interval!==null){timesync._timeout=setInterval(timesync.sync,timesync.options.interval);setTimeout(function(){timesync.sync()["catch"](function(err){return emitError(err)})},0)}return timesync}},{"./Promise":11,"./emitter.js":12,"./request/request":14,"./stat.js":16,"./util.js":18}],18:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.nextId=nextId;exports.repeat=repeat;exports.wait=wait;exports.whilst=whilst;var Promise=require("./Promise");function wait(delay){return new Promise(function(resolve){setTimeout(resolve,delay)})}function repeat(fn,times){return new Promise(function(resolve,reject){var count=0;var results=[];function recurse(){if(count<times){count++;fn().then(function(result){results.push(result);recurse()})}else{resolve(results)}}recurse()})}function whilst(condition,callback){return new Promise(function(resolve,reject){function recurse(){if(condition()){callback().then(function(){return recurse()})}else{resolve()}}recurse()})}function nextId(){return _id++}var _id=0},{"./Promise":11}]},{},[17])(17)});