@@ -58,19 +58,14 @@ export class ResourceDownloadQueue {
5858 continue ;
5959 }
6060
61- try {
62- if ( options ) {
63- const singleUrl = options . singleUrl ;
64- message = await this . downloadSingleUrl ( message , singleUrl , operation ) ;
65- } else {
66- message = await this . downloadAllPreviewUrls ( message , operation ) ;
67- }
68- this . _context . setChatMessage ( threadId , message ) ;
69- } catch ( error ) {
70- console . log ( 'Downloading Resource error: ' , error ) ;
71- } finally {
72- this . isActive = false ;
61+ if ( options ) {
62+ const singleUrl = options . singleUrl ;
63+ message = await this . downloadSingleUrl ( message , singleUrl , operation ) ;
64+ } else {
65+ message = await this . downloadAllPreviewUrls ( message , operation ) ;
7366 }
67+ this . _context . setChatMessage ( threadId , message ) ;
68+ this . isActive = false ;
7469 }
7570 }
7671
@@ -79,7 +74,7 @@ export class ResourceDownloadQueue {
7974 resourceUrl : string ,
8075 operation : ImageRequest
8176 ) : Promise < ChatMessageWithStatus > {
82- const blobUrl = await operation ( resourceUrl , this . _credential ) ;
77+ const blobUrl = await this . downloadResource ( operation , resourceUrl ) ;
8378 message = { ...message , resourceCache : { ...message . resourceCache , [ resourceUrl ] : blobUrl } } ;
8479 return message ;
8580 }
@@ -95,14 +90,24 @@ export class ResourceDownloadQueue {
9590 }
9691 for ( const attachment of attachments ) {
9792 if ( attachment . previewUrl && attachment . attachmentType === 'image' ) {
98- const blobUrl = await operation ( attachment . previewUrl , this . _credential ) ;
93+ const blobUrl = await this . downloadResource ( operation , attachment . previewUrl ) ;
9994 message . resourceCache [ attachment . previewUrl ] = blobUrl ;
10095 }
10196 }
10297 }
10398
10499 return message ;
105100 }
101+
102+ private async downloadResource ( operation : ImageRequest , url : string ) : Promise < string > {
103+ let blobUrl = URL . createObjectURL ( new Blob ( ) ) ;
104+ try {
105+ blobUrl = await operation ( url , this . _credential ) ;
106+ } catch ( error ) {
107+ console . log ( 'Downloading Resource error: ' , error ) ;
108+ }
109+ return blobUrl ;
110+ }
106111}
107112/* @conditional -compile-remove(teams-inline-images-and-file-sharing) */
108113/**
@@ -141,11 +146,28 @@ export const fetchImageSource = async (src: string, credential: CommunicationTok
141146 const headers = new Headers ( ) ;
142147 headers . append ( 'Authorization' , `Bearer ${ token } ` ) ;
143148 try {
144- return await fetch ( url , { headers } ) ;
149+ return await fetchWithTimeout ( url , { headers } ) ;
145150 } catch ( err ) {
146151 throw new ChatError ( 'ChatThreadClient.getMessage' , err as Error ) ;
147152 }
148153 }
154+ async function fetchWithTimeout (
155+ resource : string | URL | Request ,
156+ options : { timeout ?: number ; headers ?: Headers }
157+ ) : Promise < Response > {
158+ // default timeout is 30 seconds
159+ const { timeout = 30000 } = options ;
160+
161+ const controller = new AbortController ( ) ;
162+ const id = setTimeout ( ( ) => controller . abort ( ) , timeout ) ;
163+
164+ const response = await fetch ( resource , {
165+ ...options ,
166+ signal : controller . signal
167+ } ) ;
168+ clearTimeout ( id ) ;
169+ return response ;
170+ }
149171 const accessToken = await credential . getToken ( ) ;
150172 const response = await fetchWithAuthentication ( src , accessToken . token ) ;
151173 const blob = await response . blob ( ) ;
0 commit comments