I see from this question that it can be an antipattern to mix Promises with async code.
Does this, however, apply in all cases?
I can't see an easy way to avoid combining them in the following code:
- It's an alternative to setIntervalwhich waits for an invocation to complete before scheduling the next one
- However, unlike recursive setTimeout, it does not constitute an open memory leak in browsers that don't yet support TCO
Does this code embody an antipattern? And, if so, how can I remedy it without introducing a memory leak?
See, in particular, line 10: new Promise( async (resolve) => {
—this seems very non-idiomatic, but I don't see another way to accomplish: wrapping an await statement in a while loop per se, dispatching it, and returning a handle to abort the loop.
var [setRepeatedTimeout, clearRepeatedTimeout] = (() => {
    const asleep = (delay) => new Promise(resolve => setTimeout(resolve, delay));
    const repeatedTimeoutIntervals = [];
    function setRepeatedTimeout(f, delay, ...arguments) {
        //Like setInterval, but waits for an invocation to complete before scheduling the next one
        //(Supports both classic and async functions)
        const mySemaphores = {notAborted: true};
        const intervalID = repeatedTimeoutIntervals.push(mySemaphores) - 1;
        new Promise( async (resolve) => {
            await asleep(delay);
            while(mySemaphores.notAborted) {
                await f(...arguments);
                await asleep(delay);
            }
            delete repeatedTimeoutIntervals[intervalID];
        });
        return intervalID;
    }
    function clearRepeatedTimeout(intervalID) {
        //Clears loops set by setInterval()
        repeatedTimeoutIntervals[intervalID].notAborted = false;
    }
    return [setRepeatedTimeout, clearRepeatedTimeout];
})();<p><button onclick="(function createInterval(){
  const _ = {intervalID: undefined};
  _.intervalID = setRepeatedTimeout( () => {
    console.log(`Hello from intervalID ${_.intervalID}`)
  }, 2000)
})()">Create timer</button><br />
<form action="javascript:void(0);" onsubmit="(function clearInterval(intervalID){
  clearRepeatedTimeout(intervalID);
})(parseInt(event.target.elements.intervalID.value))">
<input name="intervalID" placeholder="intervalID"/><button type="submit">Clear timer</button></p> 
    