@@ -28,7 +28,10 @@ export class AbortSignalListener {
2828 this . abortSignal . removeEventListener ( 'abort' , this . abort ) ;
2929 }
3030
31- cancellablePromise < T > ( originalPromise : Promise < T > ) : Promise < T > {
31+ cancellablePromise < T > (
32+ originalPromise : Promise < T > ,
33+ onCancel ?: ( ( ) => Promise < unknown > ) | undefined ,
34+ ) : Promise < T > {
3235 if ( this . abortSignal . aborted ) {
3336 // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
3437 return Promise . reject ( this . abortSignal . reason ) ;
@@ -40,14 +43,42 @@ export class AbortSignalListener {
4043 originalPromise . then (
4144 ( resolved ) => {
4245 this . _aborts . delete ( abort ) ;
46+ onCancel ?.( ) . catch ( ( ) => {
47+ // ignore
48+ } ) ;
4349 resolve ( resolved ) ;
4450 } ,
4551 ( error : unknown ) => {
4652 this . _aborts . delete ( abort ) ;
53+ onCancel ?.( ) . catch ( ( ) => {
54+ // ignore
55+ } ) ;
4756 reject ( error ) ;
4857 } ,
4958 ) ;
5059
5160 return promise ;
5261 }
62+
63+ cancellableIterable < T > ( iterable : AsyncIterable < T > ) : AsyncIterable < T > {
64+ const iterator = iterable [ Symbol . asyncIterator ] ( ) ;
65+
66+ const earlyReturn =
67+ typeof iterator . return === 'function'
68+ ? iterator . return . bind ( iterator )
69+ : undefined ;
70+
71+ const cancellableAsyncIterator : AsyncIterator < T > = {
72+ next : ( ) => this . cancellablePromise ( iterator . next ( ) , earlyReturn ) ,
73+ } ;
74+
75+ if ( earlyReturn ) {
76+ cancellableAsyncIterator . return = ( ) =>
77+ this . cancellablePromise ( earlyReturn ( ) ) ;
78+ }
79+
80+ return {
81+ [ Symbol . asyncIterator ] : ( ) => cancellableAsyncIterator ,
82+ } ;
83+ }
5384}
0 commit comments