Created
August 27, 2024 13:30
-
-
Save anonhostpi/f85f620cbe541babe00054ad9a706d1a to your computer and use it in GitHub Desktop.
A TypeScript file for writing a promise that is forced non-blocking using setTimeout
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
async functions and promises can be a bit misleading, as they are not guaranteed to be executed asynchronously. | |
The way these work is by deferring the execution of a portion of the code to another tick of the event loop. | |
For async functions, the code is executed synchronously until the first await statement, | |
at which point the function is suspended and the rest of the code is executed | |
asynchronously on another tick when the awaited promise is resolved. | |
For promises, the executor function is executed immediately, but in | |
which tick the promise is resolved can be more granularly controlled. | |
An older trick for manipulating which tick code is executed in is to make use of setTimeout. | |
When setTimeout is called with a delay of 0, the callback is executed in the next tick of the event loop. | |
*/ | |
class ForcedPromise<T> extends Promise<T> { | |
constructor( | |
executor: ( | |
resolve: (value: T | PromiseLike<T>) => void, | |
reject: (reason?: any) => void | |
) => void, | |
){ | |
const wrapped_executor = ( | |
resolve: (value: T | PromiseLike<T>) => void, | |
reject: (reason?: any) => void | |
) => { | |
setTimeout(() => { | |
try { | |
const wrapped_out = executor(resolve, reject); | |
} catch (e) { | |
reject(e); | |
} | |
}, 0); | |
} | |
super(wrapped_executor); | |
} | |
} | |
/* | |
Example usage (tick per second counter): | |
function counter( seconds: number ){ | |
let ticks = 0; | |
let promise: ForcedPromise<void>; | |
function increment(){ | |
ticks++; | |
if( promise ) | |
return promise = new ForcedPromise<void>(increment) | |
} | |
promise = new ForcedPromise<void>(increment); | |
setTimeout(()=>{ | |
console.log( ticks/seconds, "ticks per second" ); | |
promise = null; | |
}, seconds * 1000); | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment