Created
June 15, 2025 01:26
-
-
Save JhonSmith0/23db405da7851cabdb754e15000a89e5 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
type GeneratorOrAsyncGenerator = | |
| Generator<any, any, any> | |
| AsyncGenerator<any, any, any>; | |
type GeneratorOrAsyncGeneratorFunction = (...args: any[]) => GeneratorOrAsyncGenerator; | |
type GeneratorReturn<T> = T extends Generator<any, infer R, any> ? R : never; | |
type AsyncGeneratorReturn<T> = T extends AsyncGenerator<any, infer R, any> ? R : never; | |
type GeneratorTypeOfGeneratorFunction<T extends GeneratorOrAsyncGeneratorFunction> = | |
ReturnType<T> extends AsyncGenerator<any, any, any> | |
? AsyncGeneratorReturn<ReturnType<T>> | |
: ReturnType<T> extends Generator<any, any, any> | |
? GeneratorReturn<ReturnType<T>> | |
: never; | |
export function convertGeneratorToPromise<T extends GeneratorOrAsyncGeneratorFunction>(generatorFunction: T) { | |
return (...args: Parameters<T>): Promise<GeneratorTypeOfGeneratorFunction<T>> => { | |
return new Promise(async (resolve, reject) => { | |
const generator = generatorFunction(...args) | |
async function callNextRecursively() { | |
try { | |
const result = await generator.next() | |
if (result.done) { | |
resolve(result.value) | |
} else { | |
setImmediate(callNextRecursively) | |
} | |
} catch (e) { | |
reject(e) | |
} | |
} | |
callNextRecursively() | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Essa função utilitária convertGeneratorToPromise permite transformar funções generator (ou async generator) em funções async, com o objetivo principal de processar operações intensivas sem bloquear a thread principal.
A ideia é que você possa escrever uma função síncrona intensiva, convertê-la em um Generator, e então executá-la de forma assíncrona, com pausas controladas entre os passos usando setImmediate. Isso permite dividir o processamento em pequenos blocos e manter a responsividade do event loop.
✨ Benefícios:
Evita travamentos ou bloqueios na interface (em ambientes como Node.js ou Electron)
Útil para processar grandes volumes de dados, parsing, transformações ou loops pesados
Tipado com TypeScript para suportar Generator e AsyncGenerator de forma segura
🧠 Como funciona:
Você transforma uma função síncrona intensa em um Generator, com yield nos pontos de pausa
Usa convertGeneratorToPromise para executá-la como se fosse async, com pausas entre os ciclos
O loop interno usa setImmediate para liberar a thread entre cada passo
Exemlpo de conversão:

É muito melhor que:

Pois isso vai bloquear a thread