Last active
April 29, 2020 12:36
-
-
Save Adriem/8683a8dd5aa2ee3bf460a09e30835d57 to your computer and use it in GitHub Desktop.
Revisions
-
Adriem revised this gist
Apr 29, 2020 . 1 changed file with 41 additions and 36 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -5,64 +5,69 @@ // to the decorators and wrap the result in an async generator synchronized with the original one. const compose = (...functions) => functions.reverse().reduce((decorated, decorator) => decorator(decorated)); const decorateGeneratorFunction = (...decorators) => (generatorFunction) => { let resolve; let promise = new Promise(r => resolve = r); let isGeneratorDone = false; const onYield = (yieldedResult) => { resolve(yieldedResult); promise = new Promise(r => resolve = r) }; const wrappedGenerator = async (...args) => { const generator = generatorFunction(...args); for await (let step of generator) onYield(step); isGeneratorDone = true; }; const composed = compose(...decorators, wrappedGenerator); return async function* (...args) { // Do not await composed() function. The wrappedGenerator // will call onYield(), which will advance the progress composed(...args); while (!isGeneratorDone) yield await promise; }; } // Decorate the generator and execute it, printing each yield result and awaiting for its end const demo = async () => { // Promised timeout const delay = (t, v) => new Promise(r => setTimeout(() => r(v), t)); // Generator function to be passed down to a decorator that expects an async function const originalGeneratorFn = async function* (initialValue, times) { for (let i = 1; i <= times; i++) yield await delay(500, initialValue + i); yield await delay(500, 'DONE'); }; // Decorate an asynchronous function to be called // with only an argument containing the value <0> const decorateWithInitialValue = (initialValue) => (fn) => async function (...args) { return await fn(initialValue, ...args); }; const INITIAL_VALUE = 10; const ITERATIONS = 5; const decoratedGeneratorFn = decorateGeneratorFunction( decorateWithInitialValue(INITIAL_VALUE), )(originalGeneratorFn); const generator = decoratedGeneratorFn(ITERATIONS); let result; for await (result of generator) console.log(result); return result }; main = async () => { await demo(); console.log('Finished'); }; main(); -
Adriem created this gist
Apr 29, 2020 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,68 @@ // When a generator function is decorated or composed, the composed function will not // work unless the decorator explicitly supports decorating a generator function. // // This example shows how to wrap an async generator function as an async function, pass it // to the decorators and wrap the result in an async generator synchronized with the original one. const compose = (...functions) => functions.reverse().reduce((decorated, decorator) => decorator(decorated)); const decorateGeneratorFunction = (...decorators) => (generatorFunction) => { let resolve; let promise = new Promise(r => resolve = r); let isGeneratorDone = false; const onYield = (yieldedResult) => { resolve(yieldedResult); promise = new Promise(r => resolve = r) }; const wrappedGenerator = async (...args) => { const generator = generatorFunction(...args); for await (let step of generator) onYield(step); isGeneratorDone = true; }; const composed = compose(...decorators)(wrappedGenerator); return async function* (...args) { // Do not await composed() function. The wrappedGenerator // will call onYield(), which will advance the progress composed(...args); while (!isGeneratorDone) yield await promise; }; } // Decorate the generator and execute it, printing each yield result and awaiting for its end const demo = async () => { // Promised timeout const delay = (t, v) => new Promise(r => setTimeout(() => r(v), t)); // Generator function to be passed down to a decorator that expects an async function const originalGeneratorFn = async function* (initialValue, times) { for (let i = 1; i <= times; i++) yield await delay(500, initialValue + i); yield await delay(500, 'DONE'); }; // Decorate an asynchronous function to be called // with only an argument containing the value <0> const decorateWithInitialValue = (initialValue) => (fn) => async function (...args) { return await fn(initialValue, ...args); }; const INITIAL_VALUE = 10; const ITERATIONS = 5; const decoratedGeneratorFn = decorateGeneratorFunction( decorateWithInitialValue(INITIAL_VALUE), )(originalGeneratorFn); const generator = decoratedGeneratorFn(ITERATIONS); let result; for await (result of generator) console.log(result); return result }; demo();