Skip to content

Instantly share code, notes, and snippets.

@peter-leonov
Created February 16, 2020 21:49
Show Gist options
  • Save peter-leonov/2700fefa3d46a925bfdcbe6f1cce4e5a to your computer and use it in GitHub Desktop.
Save peter-leonov/2700fefa3d46a925bfdcbe6f1cce4e5a to your computer and use it in GitHub Desktop.
Re-implementing a simple (but with a whole for loop!) async function as a generator and as a co-routine for fun
// lib
const sleep = t => new Promise(res => setTimeout(res, t));
const getRandom = () => sleep(100).then(() => Math.random());
// native solution
async function getRandomsNative(count) {
await sleep(100);
const randoms = [];
for (let i = 0; i <= count; i++) {
console.log(i);
randoms.push(await getRandom());
}
return randoms;
}
// generator based solution (remember ko?)
function exec(iter) {
function wrapper(resolve, reject) {
function next(awaitedValue) {
try {
const { done, value } = iter.next(awaitedValue);
if (done) {
resolve(value);
} else {
if (typeof value.then == "function") {
value.then(next);
} else {
next(value);
}
}
} catch (err) {
reject(err);
}
}
next(undefined);
}
return new Promise(wrapper);
}
function getRandomsGenerator(...args) {
function* inner(count) {
yield sleep(100);
const randoms = [];
for (let i = 0; i <= count; i++) {
console.log(i);
randoms.push(yield getRandom());
}
return randoms;
}
return exec(inner(...args));
}
// babel-like switch/case co-routine solution
function getRandomsCoroutine(...args) {
function getRandoms(count) {
let __step_a = 0,
__step_b = 0;
var randoms, i;
return function inner(__v) {
switch (__step_a) {
case 0:
__step_a = 1;
return sleep(100);
case 1:
randoms = [];
i = 0;
__step_a = 2;
case 2:
__loop_b: for (;;) {
switch (__step_b) {
case 0:
if (!(i <= count)) break __loop_b;
__step_b = 1;
case 1:
console.log(i);
__step_b = 2;
return getRandom();
case 2:
randoms.push(__v);
}
i++;
__step_b = 0;
continue;
}
__step_b = 0;
__step_a = 3;
case 3:
__step_a = 4;
inner.finished = true;
return randoms;
}
};
}
const co = getRandoms(...args);
return exec({
next: v => ({
value: co(),
// yeah, everything looks like a generation if you used to use one
done: co.finished
})
});
}
async function main() {
console.log("getRandomsNative()");
await getRandomsNative(10);
console.log("getRandomsGenerator()");
await getRandomsGenerator(10);
console.log("getRandomsCoroutine()");
await getRandomsCoroutine(10);
console.log("done");
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment