timeout-flow
Version:
Fluent, composable, pauseable JavaScript timers and time control flows — plus RAF utilities for frame-based logic.
8 lines (7 loc) • 7.22 kB
JavaScript
// TimeoutFlow - Fluent timer + RAF control library
var O=e=>{throw TypeError(e)};var G=(e,t,n)=>t.has(e)||O("Cannot "+n);var u=(e,t,n)=>(G(e,t,"read from private field"),n?n.call(e):t.get(e)),d=(e,t,n)=>t.has(e)?O("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),m=(e,t,n,l)=>(G(e,t,"write to private field"),l?l.call(e,n):t.set(e,n),n),S=(e,t,n)=>(G(e,t,"access private method"),n);var Q=(e,t,n,l)=>({set _(o){m(e,t,o,n)},get _(){return u(e,t,l)}});var U=Object.freeze(JSON.parse(`{
"ms": 1,
"s": 1000,
"m": 60000,
"h": 3600000
}`));function h(e){if(typeof e=="number"&&Number.isFinite(e))return e;if(typeof e!="string")throw new TypeError(`Expected a duration string or number, got ${typeof e}`);e=e.toLowerCase().trim();let t=e.match(/^(\d+(?:\.\d+)?)\s*(ms|s|m|h)$/);if(!t)throw new Error(`Invalid duration format: "${e}". Expected formats like "500ms", "2s", "1.5m", or "1h".`);let[,n,l]=t;return parseFloat(n)*U[l]}var k,$,R,I,D,C=class{constructor(t){d(this,k);d(this,$,null);d(this,R);d(this,I,null);d(this,D,!1);m(this,k,h(t)),m(this,R,u(this,k))}get isRunning(){return u(this,D)}pause(){u(this,D)&&(clearTimeout(u(this,I)),m(this,R,u(this,R)-(Date.now()-u(this,$))),m(this,D,!1))}resume(t,n=null){!u(this,D)&&u(this,R)>0&&(m(this,$,Date.now()),m(this,D,!0),m(this,I,setTimeout(()=>{m(this,D,!1),t?.()},n??u(this,R))))}cancel(){clearTimeout(u(this,I)),m(this,D,!1),m(this,I,null)}reset(){this.cancel(),m(this,R,u(this,k))}};k=new WeakMap,$=new WeakMap,R=new WeakMap,I=new WeakMap,D=new WeakMap;var _=class extends C{constructor(t,n,l){super(t),this.resume(()=>{n?.(),l?.()})}};function H(e,t,n){return new _(e,t,n)}var L,N,q,b,T,v,E,M,z,B=class{constructor(t,n,l=1/0,o=!1){d(this,M);d(this,L);d(this,N);d(this,q);d(this,b,0);d(this,T,!1);d(this,v,null);d(this,E,()=>{var t;if(u(this,b)>=u(this,q)){this.cancel();return}(t=u(this,N))==null||t.call(this,Q(this,b)._++),S(this,M,z).call(this)});m(this,L,h(t)),m(this,N,n),m(this,q,l),o?u(this,E).call(this):S(this,M,z).call(this)}get count(){return u(this,b)}get isRunning(){return u(this,T)}pause(){u(this,v)?.pause(),m(this,T,!1)}resume(){!u(this,T)&&u(this,b)<u(this,q)&&(u(this,v)?.resume(u(this,E)),m(this,T,!0))}cancel(){u(this,v)?.cancel(),m(this,T,!1)}reset(t=!1){this.cancel(),m(this,b,0),t&&S(this,M,z).call(this)}};L=new WeakMap,N=new WeakMap,q=new WeakMap,b=new WeakMap,T=new WeakMap,v=new WeakMap,E=new WeakMap,M=new WeakSet,z=function(){m(this,v,new C(u(this,L))),m(this,T,!0),u(this,v).resume(u(this,E))};function K(e,t,n=1/0,l=!1){return new B(e,t,n,l)}function V(){let e=[],t=0,n=!1,l=!1,o=!1,i=1/0,s=0,f=null,a=new Map,c=null,y=[],x=!1,F=null,A=null,w={after(r,p){return e.push({type:"after",duration:r,fn:p}),w},every(r,p,W=1/0){return e.push({type:"every",duration:r,fn:p,times:W,whileCondition:F,doWhileCondition:A}),F=null,A=null,w},loop(r=!0){return o=!0,i=r===!0?1/0:r,w},onFinish(r){return f=r,w},start(){return l=!1,n=!1,t=0,s=0,P(),w},pause(){n||l||(n=!0,e[t]?.controller?.pause?.())},resume(){!n||l||(n=!1,e[t]?.controller?.resume?.())},cancel(){l=!0;let r=e[t];r?.controller?.cancel?.(),r.controller=null},reset(){return w.cancel(),e.length=0,t=0,s=0,f=null,w},get isPaused(){return n},label(r){return a.set(r,e.length),w},jumpTo(r){return c=r,w},if(r){return y.push(()=>typeof r=="function"?r():!!r),w},unless(r){return y.push(()=>!(typeof r=="function"?r():r)),w},while(r){return F=()=>typeof r=="function"?r():!!r,w},doWhile(r){return A=()=>typeof r=="function"?r():!!r,w}};function g(r=null){r?.controller&&(r.controller=null),t++,P()}function P(){if(l||n)return;if(c){let p=a.get(c);if(typeof p=="number")t=p;else throw new Error(`Label "${c}" not found`);c=null}if(y.length>0&&(y.shift()()||(x=!0)),x){let p=e[t];if(!p||p.type==="label")x=!1;else return g(r)}let r=e[t];if(!r||t>=e.length){o&&++s<i?(t=0,P()):f?.();return}if(r.type==="after"){r.controller=H(r.duration,r.fn,()=>g(r));return}if(r.type==="every"){let p=0,W=!0,j=K(r.duration,()=>{if(!(n||l)&&(r.whileCondition&&!r.whileCondition()||(r.fn(p++),W=!1,!W&&r.doWhileCondition&&!r.doWhileCondition())||p>=r.times))return j.cancel(),g(r)},r.times);r.controller=j}if(r.type==="label")return g(r)}return w}function J(e,t){let n,l;if(typeof e=="function"?(n=e,l=t):(n=t,l=e),typeof n!="function")throw new TypeError(`Expected a function as one argument, got: ${typeof n}`);let o=h(l);return{fn:n,delay:o}}function X(e,t,n=!0){let{fn:l,delay:o}=J(e,t),i=0,s=null,f=function(...a){let c=this,y=Date.now(),x=y-i;x>=o?(i=y,l.apply(c,a)):n&&!s&&(s=setTimeout(()=>{i=Date.now(),s=null,l.apply(c,a)},o-x))};return f.cancel=()=>{clearTimeout(s),s=null},f}function Y(e,t){let{fn:n,delay:l}=J(e,t),o=null,i=function(...s){clearTimeout(o),o=setTimeout(()=>n.apply(this,s),l)};return i.cancel=()=>{clearTimeout(o),o=null},i}function Z(e,{interval:t="250ms",timeout:n}={}){return new Promise((l,o)=>{let i=Date.now(),s=typeof t=="string"?h(t):t,f=n?h(n):null,c=setInterval(()=>{e()?(clearInterval(c),l()):f&&Date.now()-i>=f&&(clearInterval(c),o(new Error("waitFor timed out")))},s)})}async function ee(e,{attempts:t=3,delay:n="500ms",backoff:l=!1}={}){let o=h(n);for(let i=0;i<t;i++)try{return await e()}catch(s){if(i===t-1)throw s;let f=l?o*Math.pow(2,i):o;await new Promise(a=>setTimeout(a,f))}}function te(e,t,n){let l=typeof e=="string"?h(e):e,o=null,i=null,s=null,f=0,a=!0,c=A=>{if(!a)return;i==null&&(i=A),A-i+f>=l?(a=!1,t?.(),n?.()):o=requestAnimationFrame(c)},y=()=>{a&&o!==null&&(cancelAnimationFrame(o),s=performance.now(),a=!1)},x=()=>{!a&&s!==null&&(f+=performance.now()-s,a=!0,o=requestAnimationFrame(c))},F=()=>{o!==null&&(cancelAnimationFrame(o),o=null),a=!1};return o=requestAnimationFrame(c),{pause:y,resume:x,cancel:F,get isRunning(){return a}}}function ne(e,t,n=1/0,l=!1){let o=typeof e=="string"?h(e):e,i=null,s=null,f=null,a=!1,c=!1,y=0,x=0,F=p=>{if(!a||c)return;if(s==null&&(s=p,f=p),p-f+y>=o){if(x>=n){g();return}t?.(),x++,f=p,y=0}i=requestAnimationFrame(F)},A=()=>{a&&!c&&(c=!0,y+=performance.now()-f,cancelAnimationFrame(i))},w=()=>{a&&c&&(c=!1,f=performance.now(),i=requestAnimationFrame(F))},g=()=>{i!==null&&(cancelAnimationFrame(i),i=null),a=!1,c=!1,s=null,f=null,y=0},P=(p=!1)=>{g(),x=0,p&&r()},r=()=>{l&&(t?.(),x++),a=!0,c=!1,f=performance.now(),i=requestAnimationFrame(F)};return r(),{pause:A,resume:w,cancel:g,reset:P,get isRunning(){return a&&!c},get count(){return x}}}function re(e,t){let[n,l]=typeof e=="function"?[0,e]:[h(e),t],o=null,i=null,s=0,f=a=>{a-s>=n?(l(...i),o=null):o=requestAnimationFrame(f)};return(...a)=>{i=a,s=performance.now(),o!==null&&cancelAnimationFrame(o),o=requestAnimationFrame(f)}}function oe(e,t=0){let n=!1,l=null,o=0;return(...i)=>{l=i,n||(n=!0,requestAnimationFrame(function s(){o>=t?(e(...l),o=0,n=!1):(o++,requestAnimationFrame(s))}))}}function le(e,{timeout:t}={}){return new Promise((n,l)=>{let o=performance.now(),i=t?h(t):null,s=f=>{if(e())return n();if(i&&f-o>=i)return l(new Error("waitForRaf timed out"));requestAnimationFrame(s)};requestAnimationFrame(s)})}export{H as after,te as afterRaf,Y as debounce,re as debounceRaf,K as every,ne as everyRaf,V as flow,h as parseDuration,ee as retry,X as throttle,oe as throttleRaf,Z as waitFor,le as waitForRaf};