Skip to content

Commit

Permalink
fix: it-foreach should only await thenables
Browse files Browse the repository at this point in the history
If a synchronous function is passed to `it-foreach` we don't need
to `await` on the result - this artificial asynchronicity introduces
unnecessary latency on hot code paths.
  • Loading branch information
achingbrain committed Nov 11, 2023
1 parent e083c0f commit 56f7077
Showing 1 changed file with 18 additions and 4 deletions.
22 changes: 18 additions & 4 deletions packages/it-foreach/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ function isAsyncIterable <T> (thing: any): thing is AsyncIterable<T> {
return thing[Symbol.asyncIterator] != null
}

function isPromise <T = unknown> (thing: any): thing is Promise<T> {
return thing?.then != null
}

/**
* Invokes the passed function for each item in an iterable
*/
Expand All @@ -13,9 +17,14 @@ function forEach <T> (source: Iterable<T> | AsyncIterable<T>, fn: (thing: T) =>
function forEach <T> (source: Iterable<T> | AsyncIterable<T>, fn: (thing: T) => void | Promise<void>): AsyncGenerator<T, void, undefined> | Generator<T, void, undefined> {
if (isAsyncIterable(source)) {
return (async function * () {
for await (const thing of source) {
await fn(thing)
yield thing
for await (const val of source) {
const res = fn(val)

if (isPromise(res)) {
await res
}

yield val
}
})()
}
Expand All @@ -35,7 +44,12 @@ function forEach <T> (source: Iterable<T> | AsyncIterable<T>, fn: (thing: T) =>
yield value

for await (const val of peekable) {
await fn(val)
const res = fn(val)

if (isPromise(res)) {
await res
}

yield val
}
})()
Expand Down

0 comments on commit 56f7077

Please sign in to comment.