@@ -397,114 +397,3 @@ export function sleep(duration: number = 0): Promise<void> {
397397 const schedule = globals ?. clock ?. setTimeout ?? setTimeout
398398 return new Promise ( ( r ) => schedule ( r , Math . max ( duration , 0 ) ) )
399399}
400-
401- /**
402- * Similar to waitUntil but with enhanced cancellation support.
403- * Waits until the predicate returns true or the operation is cancelled.
404- * Continuously checks for cancellation even when waiting for the next chunk.
405- *
406- * @param fn Function whose result is checked
407- * @param options Configuration options including timeout, interval, and cancellation token
408- * @returns Result of fn(), or undefined if cancelled
409- */
410- export async function waitUntilWithCancellation < T > (
411- fn : ( ) => Promise < T > ,
412- options : WaitUntilOptions & {
413- cancellationToken : CancellationToken
414- }
415- ) : Promise < T | undefined > {
416- const { cancellationToken, ...waitOptions } = options
417-
418- // Set up cancellation listener
419- let cancellationListener : { dispose : ( ) => void } | undefined
420- let checkInterval : NodeJS . Timeout | number | undefined
421- let isCancelled = false
422-
423- try {
424- return await new Promise < T | undefined > ( ( resolve , reject ) => {
425- // Set up cancellation listener that will resolve with undefined instead of rejecting
426- if ( cancellationToken ) {
427- cancellationListener = cancellationToken . onCancellationRequested ( ( ) => {
428- if ( checkInterval ) {
429- globals . clock . clearInterval ( checkInterval )
430- }
431- isCancelled = true
432- resolve ( undefined ) // Resolve with undefined instead of rejecting
433- } )
434- }
435-
436- // Use the existing waitUntil function with a wrapper that checks for cancellation
437- waitUntil (
438- async ( ) => {
439- // Check for cancellation before executing function
440- if ( cancellationToken . isCancellationRequested ) {
441- isCancelled = true
442- return undefined // Return undefined to signal cancellation
443- }
444-
445- const result = await fn ( )
446-
447- // Check for cancellation after executing function
448- if ( cancellationToken . isCancellationRequested ) {
449- isCancelled = true
450- return undefined // Return undefined to signal cancellation
451- }
452-
453- return result
454- } ,
455- {
456- ...waitOptions ,
457- retryOnFail : ( error ) => {
458- // Don't retry if cancelled
459- if ( isCancelled ) {
460- return false
461- }
462-
463- // Use the original retryOnFail option if provided
464- if ( typeof waitOptions . retryOnFail === 'function' ) {
465- return waitOptions . retryOnFail ( error )
466- }
467- return waitOptions . retryOnFail ?? false
468- } ,
469- }
470- )
471- . then ( ( result ) => {
472- // If cancelled during execution, resolve with undefined
473- if ( isCancelled ) {
474- resolve ( undefined )
475- } else {
476- resolve ( result )
477- }
478- } )
479- . catch ( ( error ) => {
480- // If cancelled during execution, resolve with undefined
481- if ( isCancelled ) {
482- resolve ( undefined )
483- } else {
484- reject ( error )
485- }
486- } )
487-
488- // Set up an interval to periodically check for cancellation
489- // This ensures we don't miss cancellation events while waiting for the next chunk
490- checkInterval = globals . clock . setInterval (
491- ( ) => {
492- if ( cancellationToken . isCancellationRequested && ! isCancelled ) {
493- isCancelled = true
494- globals . clock . clearInterval ( checkInterval )
495- resolve ( undefined ) // Resolve with undefined instead of rejecting
496- }
497- } ,
498- Math . min ( waitOptions . interval ?? waitUntilDefaultInterval , 100 )
499- )
500- } )
501- } finally {
502- // Clean up resources
503- if ( checkInterval ) {
504- globals . clock . clearInterval ( checkInterval )
505- }
506- if ( cancellationListener ) {
507- cancellationListener . dispose ( )
508- }
509- }
510- }
0 commit comments