Skip to content

Instantly share code, notes, and snippets.

@Zemnmez
Last active January 27, 2020 02:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zemnmez/3e85347fe8bf56b8674bf6c2a4358c15 to your computer and use it in GitHub Desktop.
Save Zemnmez/3e85347fe8bf56b8674bf6c2a4358c15 to your computer and use it in GitHub Desktop.
type Eventually<T> =
T | Promise<T>;
type EventuallyIterable<T> = Iterable<T> | AsyncIterable<T>
const map:
<T,O>(f: Eventually<(v: T, i: number) => O>, v: EventuallyIterable<T>) => EventuallyIterable<O>
=
async function*(f, iter) {
let n = 0;
for await (let value of iter) yield (await f)(value, n++);
}
;
type RepeatTupleMap<T> = {
0: [],
1: [T],
2: [T,T],
3: [T,T,T],
4: [T,T,T,T],
5: [T,T,T,T,T],
6: [T,T,T,T,T,T],
7: [T,T,T,T,T,T,T],
8: [T,T,T,T,T,T,T,T]
}
type RepeatTuple<N extends number, T> =
N extends keyof RepeatTupleMap<T>? RepeatTupleMap<T>[N]: readonly T[]
const chunk:
<N extends number>(size: Eventually<N>) => <T>(v: EventuallyIterable<T>) => EventuallyIterable<RepeatTuple<N,T>>
=
<N extends number>(size: Eventually<N>) => <T>(iter: EventuallyIterable<T>) => (async function*() {
let bucket: T[] = [];
for await (let value of iter) {
bucket.push(value);
if (bucket.length == await size) {
yield bucket as RepeatTuple<N,T>;
bucket = [];
}
}
})()
;
const EventuallyIterable:
<T>(I: EventuallyIterable<Eventually<T>>) => EventuallyIterable<T>
=
async function*<T>(I: EventuallyIterable<Eventually<T>>): EventuallyIterable<T> {
for await (let value of I) yield await value
}
;
/** perform a promise iterator lazily in chunks */
const chunkedPromise:
<N extends number>(N: Eventually<N>) =>
<T>(I: EventuallyIterable<T>) => EventuallyIterable<Promise<RepeatTuple<N,T>>>
=
<N extends number>(N: Eventually<N>) =>
<T>(I: EventuallyIterable<T>) =>
map(v => Promise.all(v) as Promise<RepeatTuple<N,T>>, chunk(N)(I));
;
const flat:
<T>(I: EventuallyIterable<EventuallyIterable<T>>) => EventuallyIterable<T>
=
async function*(I) {
for await (let chunk of I) for await (let member of chunk) yield member
}
;
const throttledPromise:
<N extends number>(N:N) =>
<T>(I: EventuallyIterable<T>) => EventuallyIterable<T>
=
N => I => flat(EventuallyIterable(chunkedPromise(N)(I)))
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment