67 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			67 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
|  | /** | ||
|  |  * Timeout handling utilities | ||
|  |  */ | ||
|  | 
 | ||
|  | import * as plugins from '../webrequest.plugins.js'; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Create an AbortController with timeout | ||
|  |  */ | ||
|  | export function createTimeoutController(timeoutMs: number): { | ||
|  |   controller: AbortController; | ||
|  |   cleanup: () => void; | ||
|  | } { | ||
|  |   const controller = new AbortController(); | ||
|  |   let timeoutId: any; | ||
|  | 
 | ||
|  |   // Set up timeout
 | ||
|  |   plugins.smartdelay | ||
|  |     .delayFor(timeoutMs) | ||
|  |     .then(() => { | ||
|  |       controller.abort(); | ||
|  |     }) | ||
|  |     .then((result) => { | ||
|  |       timeoutId = result; | ||
|  |     }); | ||
|  | 
 | ||
|  |   // Cleanup function to clear timeout
 | ||
|  |   const cleanup = () => { | ||
|  |     if (timeoutId !== undefined) { | ||
|  |       // smartdelay doesn't expose a cancel method, so we just ensure
 | ||
|  |       // the controller won't abort if already completed
 | ||
|  |     } | ||
|  |   }; | ||
|  | 
 | ||
|  |   return { controller, cleanup }; | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Execute a fetch with timeout | ||
|  |  */ | ||
|  | export async function fetchWithTimeout( | ||
|  |   url: string, | ||
|  |   init: RequestInit, | ||
|  |   timeoutMs: number, | ||
|  | ): Promise<Response> { | ||
|  |   const { controller, cleanup } = createTimeoutController(timeoutMs); | ||
|  | 
 | ||
|  |   try { | ||
|  |     const response = await fetch(url, { | ||
|  |       ...init, | ||
|  |       signal: controller.signal, | ||
|  |     }); | ||
|  | 
 | ||
|  |     cleanup(); | ||
|  |     return response; | ||
|  |   } catch (error) { | ||
|  |     cleanup(); | ||
|  | 
 | ||
|  |     // Re-throw with more informative error if it's a timeout
 | ||
|  |     if (error instanceof Error && error.name === 'AbortError') { | ||
|  |       throw new Error(`Request timeout after ${timeoutMs}ms: ${url}`); | ||
|  |     } | ||
|  | 
 | ||
|  |     throw error; | ||
|  |   } | ||
|  | } |