UNPKG

caf

Version:

Cancelable Async Flows: a wrapper to treat generators as cancelable async functions

5 lines 2.5 kB
/*! CAF: cag.mjs v15.0.1 (c) 2022 Kyle Simpson MIT License: http://getify.mit-license.org */ import CAF from"./caf.mjs";import{TIMEOUT_TOKEN,UNSET,getSignalReason,cancelToken,signalPromise,processTokenOrSignal,deferred,isFunction,isPromise}from"./shared.mjs";onceEvent=CAF(onceEvent);export default Object.assign(CAG,{onEvent:onEvent,onceEvent:onceEvent});export{onEvent};export{onceEvent};var awaiteds=new WeakSet;const unset=Symbol("unset"),returned=Symbol("returned"),canceled=Symbol("canceled");function CAG(e){return function instance(n,...r){var t,a;if(({tokenOrSignal:n,signal:t,signalPr:a}=processTokenOrSignal(n)),t.aborted){let e=getSignalReason(t);throw e=e!==UNSET?e:"Aborted",e}var o=deferred(),{it:i,ait:l}=runner(e,o.pr,onComplete,t,...r),s=l.return;return l.return=function doReturn(e){try{return o.pr.resolved=!0,o.resolve(returned),Promise.resolve(i.return(e))}finally{s.call(l),onComplete()}},l;function onComplete(){n&&n!==t&&n[TIMEOUT_TOKEN]&&n.abort(),l&&(l.return=s,n=o=i=l=s=null)}}}function onEvent(e,n,r,t=!1){var a,o,i=!1,l=CAG((function*eventStream({pwait:e}){i||start();try{for(;;){if(0==a.length){let{pr:e,resolve:n}=deferred();a.push(e),o.push(n)}yield yield e(a.shift())}}finally{isFunction(n.removeEventListener)?n.removeEventListener(r,handler,t):isFunction(n.removeListener)?n.removeListener(r,handler):isFunction(n.off)&&n.off(r,handler),a.length=o.length=0}}))(e,n,r,t);return l.start=start,l;function start(){i||(i=!0,a=[],o=[],isFunction(n.addEventListener)?n.addEventListener(r,handler,t):isFunction(n.addListener)?n.addListener(r,handler):isFunction(n.on)&&n.on(r,handler))}function handler(e){if(o.length>0){o.shift()(e)}else{let{pr:n,resolve:r}=deferred();a.push(n),r(e)}}}function*onceEvent(e,n,r,t=!1){try{var a=onEvent(e,n,r,t);return(yield a.next()).value}finally{a.return()}}function pwait(e){var n=Promise.resolve(e);return awaiteds.add(n),n}function runner(e,n,r,t,...a){var o=e.call(this,{signal:t,pwait:pwait},...a);e=a=null;var i=t.pr.catch((e=>{throw{[canceled]:!0,reason:e}}));return i.catch((()=>{})),{it:o,ait:async function*runner(){var e,t=unset;try{for(;!n.resolved;)if(t!==unset?(e=t,t=unset,e=o.throw(e)):e=o.next(e),isPromise(e.value))if(awaiteds.has(e.value)){awaiteds.delete(e.value);try{if((e=await Promise.race([n,i,e.value]))===returned)return}catch(e){if(e[canceled]){let n=o.return();throw void 0!==n.value?n.value:e.reason}t=e}}else e=yield e.value;else{if(e.done)return e.value;e=yield e.value}}finally{o=n=null,r()}}()}}