1+ import { isPromise } from '../jsutils/isPromise.js' ;
12import type { PromiseOrValue } from '../jsutils/PromiseOrValue.js' ;
23
4+ import { withCleanup } from './withCleanup.js' ;
5+
36/**
47 * Given an AsyncIterable and a callback function, return an AsyncIterator
58 * which produces values mapped via calling the callback function.
69 */
7- export function mapAsyncIterable < T , U , R = undefined > (
8- iterable : AsyncGenerator < T , R , void > | AsyncIterable < T > ,
10+ export function mapAsyncIterable < T , U > (
11+ iterable : AsyncGenerator < T > | AsyncIterable < T > ,
912 callback : ( value : T ) => PromiseOrValue < U > ,
10- ) : AsyncGenerator < U , R , void > {
11- const iterator = iterable [ Symbol . asyncIterator ] ( ) ;
12-
13- async function mapResult (
14- promise : Promise < IteratorResult < T , R > > ,
15- ) : Promise < IteratorResult < U , R > > {
16- const result = await promise ;
17- if ( result . done ) {
18- return result ;
19- }
20-
21- const value = result . value ;
22- try {
23- return { value : await callback ( value ) , done : false } ;
24- } catch ( error ) {
25- await returnIgnoringErrors ( ) ;
26- throw error ;
27- }
28- }
29-
30- async function returnIgnoringErrors ( ) : Promise < void > {
13+ ) : AsyncGenerator < U , void , void > {
14+ return withCleanup ( mapAsyncIterableImpl ( iterable , callback ) , async ( ) => {
15+ const iterator = iterable [ Symbol . asyncIterator ] ( ) ;
3116 if ( typeof iterator . return === 'function' ) {
3217 try {
3318 await iterator . return ( ) ; /* c8 ignore start */
@@ -36,44 +21,19 @@ export function mapAsyncIterable<T, U, R = undefined>(
3621 /* ignore error */
3722 } /* c8 ignore stop */
3823 }
39- }
40-
41- const asyncDispose : typeof Symbol . asyncDispose =
42- Symbol . asyncDispose /* c8 ignore start */ ??
43- Symbol . for ( 'Symbol.asyncDispose' ) ; /* c8 ignore stop */
44-
45- return {
46- async next ( ) {
47- return mapResult ( iterator . next ( ) ) ;
48- } ,
49- async return ( ) : Promise < IteratorResult < U , R > > {
50- // If iterator.return() does not exist, then type R must be undefined.
51- return typeof iterator . return === 'function'
52- ? mapResult ( iterator . return ( ) )
53- : { value : undefined as any , done : true } ;
54- } ,
55- async throw ( error ?: unknown ) {
56- if ( typeof iterator . throw === 'function' ) {
57- return mapResult ( iterator . throw ( error ) ) ;
58- }
59-
60- if ( typeof iterator . return === 'function' ) {
61- await returnIgnoringErrors ( ) ;
62- }
24+ } ) ;
25+ }
6326
64- throw error ;
65- } ,
66- [ Symbol . asyncIterator ] ( ) {
67- return this ;
68- } ,
69- async [ asyncDispose ] ( ) {
70- await this . return ( undefined as R ) ;
71- if (
72- typeof ( iterable as AsyncGenerator < T , R , void > ) [ asyncDispose ] ===
73- 'function'
74- ) {
75- await ( iterable as AsyncGenerator < T , R , void > ) [ asyncDispose ] ( ) ;
76- }
77- } ,
78- } ;
27+ async function * mapAsyncIterableImpl < T , U , R = undefined > (
28+ iterable : AsyncGenerator < T , R , void > | AsyncIterable < T > ,
29+ mapFn : ( value : T ) => PromiseOrValue < U > ,
30+ ) : AsyncGenerator < U , void , void > {
31+ for await ( const value of iterable ) {
32+ const result = mapFn ( value ) ;
33+ if ( isPromise ( result ) ) {
34+ yield await result ;
35+ continue ;
36+ }
37+ yield result ;
38+ }
7939}
0 commit comments