I see from this question that it can be an antipattern to mix Promise
s 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
setInterval
which 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>