loopWithDelayNonAsync.js

node v16.0.0
version: 0.1.4
endpointsharetweet
function loopWithDelayNonAsync({ doWhat, stopWhen, minInterval }) { return new Promise((resolveWorkflow, rejectWorkflow) => { let interval; // a helper to transition to the next state, // when the pending promise is fulfilled const transition = ({ pending, next }) => { // note: we need .catch() because next may throw, // in which case we fail the whole workflow pending.then(next).catch(rejectWorkflow); } // start with step1 step1(); // step1 will transition to step2 after completing a doWhat task function step1() { if (!stopWhen()) { // start the interval timing here interval = startInterval(minInterval); // doWhat may or may not return a promise, // thus we wrap its result with a promise const pending = Promise.resolve(doWhat()); transition({ pending, next: step2 }); } else { // finish the whole workflow console.log("finished."); resolveWorkflow(); } } // step2 will transition to step3 after completing a delay function step2() { transition({ pending: interval(), next: step3 }); } // step3 will transition to step1 after showing the time lapse function step3(prevStepResults) { // prevStepResults is what the pending promise // from step2 has been resolved to console.log(`resumed after ${prevStepResults}ms...`); step1(); } }); } await loopWithDelayNonAsync({ doWhat: doSomethingForMs(150), stopWhen: stopAfterMs(2000), minInterval: 500 }); // a simple delay helper (in every single codebase :) function delay(ms) { return new Promise(r => setTimeout(r, ms)); } // a higher-order helper to calculate a timelapse function startTimeLapse() { const startTime = Date.now(); return () => Date.now() - startTime; } // a higher-order helper for a minimal interval delay function startInterval(ms) { const sinceStarted = startTimeLapse(); return () => { const sinceDelayed = startTimeLapse(); return delay(Math.max(ms - sinceStarted(), 0)).then(sinceDelayed); }; } // a higher-order helper to simulate an asynchronous task function doSomethingForMs(ms) { let count = 0; return async () => { const elapsed = startTimeLapse(); await delay(ms); // simulate an asynchronous task console.log(`done something for the ${++count} time, it took ${elapsed()}ms`); } } // a higher-order helper to tell when to stop function stopAfterMs(ms) { const elapsed = startTimeLapse(); return () => elapsed() > ms; }
Loading…

no comments

    sign in to comment