Last active
February 27, 2022 21:52
-
-
Save itacirgabral/211f24629e9bb3d1a724def568bfb5ed to your computer and use it in GitHub Desktop.
typescript async generator operator
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
import Yallist from 'yallist' | |
import { setTimeout } from 'timers/promises' | |
type Bread = { | |
[key: string]: string; | |
} | |
const mkStepwand = ({ delay = 1000, delta = 200, breads = [] }: { delay?: number; delta?: number; breads?: Array<Bread> }) => { | |
const indians = new Yallist<{ goodFor: number; bread: Bread}>() | |
let dontStop = true | |
for (const bread of breads) { | |
indians.push({ | |
bread, | |
goodFor: delay + Math.trunc(delta * (Math.random() - 0.5)) | |
}) | |
} | |
const steps = () => indians.toArray().map(el => el.bread) | |
const dates = () => indians.toArray().map(el => el.goodFor) | |
let blockerResolve: (value: unknown) => void | |
let blockerReject: (value: unknown) => void | |
let blocker = new Promise((resolve, reject) => { | |
blockerResolve = resolve | |
blockerReject = reject | |
}) | |
const close = () => { | |
dontStop = false | |
blockerReject(null) | |
} | |
const pub = (bread: Bread) => { | |
indians.push({ | |
bread, | |
goodFor: delay + Math.trunc(delta * (Math.random() - 0.5)) | |
}) | |
if (indians.length === 1) { | |
blockerResolve(null) | |
} | |
} | |
const pubOver = (bread: Bread) => { | |
indians.unshift({ | |
bread, | |
goodFor: delay + Math.trunc(delta * (Math.random() - 0.5)) | |
}) | |
if (indians.length === 1) { | |
blockerResolve(null) | |
} | |
} | |
const gen = async function * gen () { | |
while (dontStop) { | |
if (indians.head) { | |
const sleepms = indians.head?.value.goodFor ?? 0 | |
await setTimeout(sleepms > delta ? sleepms : delta) | |
const bread = indians.shift()?.bread | |
if (bread && dontStop) { | |
yield bread | |
} else { | |
dontStop = false | |
console.log(`dontStop=${dontStop}`) | |
} | |
} else { | |
await blocker | |
blocker = new Promise((resolve, reject) => { | |
blockerResolve = resolve | |
blockerReject = reject | |
}) | |
} | |
} | |
} | |
return { | |
pub, | |
pubOver, | |
gen, | |
steps, | |
dates, | |
close | |
} | |
} | |
export default mkStepwand |
Author
itacirgabral
commented
Feb 27, 2022
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment