Skip to content

Commit c3d0cd4

Browse files
authored
Loader: Add abort(). (#31276)
* Loader: Add `abort()`. * EventDispatcher: Add `removeEventListeners()`. * LoadingManager: Remove `dispose()`. * Loaders: Recreate `AbortController`. * LoadingManager: New abort approach. * Clean up. * Loaders: Add `AbortSignal.any()` fallback. * LoadingManager: Add note about `AbortSignal.any()`.
1 parent 4f67fd3 commit c3d0cd4

File tree

4 files changed

+83
-1
lines changed

4 files changed

+83
-1
lines changed

src/loaders/FileLoader.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ class FileLoader extends Loader {
5555
*/
5656
this.responseType = '';
5757

58+
/**
59+
* Used for aborting requests.
60+
*
61+
* @private
62+
* @type {AbortController}
63+
*/
64+
this._abortController = new AbortController();
65+
5866
}
5967

6068
/**
@@ -121,7 +129,7 @@ class FileLoader extends Loader {
121129
const req = new Request( url, {
122130
headers: new Headers( this.requestHeader ),
123131
credentials: this.withCredentials ? 'include' : 'same-origin',
124-
// An abort controller could be added within a future PR
132+
signal: ( typeof AbortSignal.any === 'function' ) ? AbortSignal.any( [ this._abortController.signal, this.manager.abortController.signal ] ) : this._abortController.signal
125133
} );
126134

127135
// record states ( avoid data race )
@@ -338,6 +346,20 @@ class FileLoader extends Loader {
338346

339347
}
340348

349+
/**
350+
* Aborts ongoing fetch requests.
351+
*
352+
* @return {FileLoader} A reference to this instance.
353+
*/
354+
abort() {
355+
356+
this._abortController.abort();
357+
this._abortController = new AbortController();
358+
359+
return this;
360+
361+
}
362+
341363
}
342364

343365

src/loaders/ImageBitmapLoader.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ class ImageBitmapLoader extends Loader {
6666
*/
6767
this.options = { premultiplyAlpha: 'none' };
6868

69+
/**
70+
* Used for aborting requests.
71+
*
72+
* @private
73+
* @type {AbortController}
74+
*/
75+
this._abortController = new AbortController();
76+
6977
}
7078

7179
/**
@@ -154,6 +162,7 @@ class ImageBitmapLoader extends Loader {
154162
const fetchOptions = {};
155163
fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
156164
fetchOptions.headers = this.requestHeader;
165+
fetchOptions.signal = ( typeof AbortSignal.any === 'function' ) ? AbortSignal.any( [ this._abortController.signal, this.manager.abortController.signal ] ) : this._abortController.signal;
157166

158167
const promise = fetch( url, fetchOptions ).then( function ( res ) {
159168

@@ -191,6 +200,20 @@ class ImageBitmapLoader extends Loader {
191200

192201
}
193202

203+
/**
204+
* Aborts ongoing fetch requests.
205+
*
206+
* @return {ImageBitmapLoader} A reference to this instance.
207+
*/
208+
abort() {
209+
210+
this._abortController.abort();
211+
this._abortController = new AbortController();
212+
213+
return this;
214+
215+
}
216+
194217
}
195218

196219
export { ImageBitmapLoader };

src/loaders/Loader.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class Loader {
6767
* This method needs to be implemented by all concrete loaders. It holds the
6868
* logic for loading assets from the backend.
6969
*
70+
* @abstract
7071
* @param {string} url - The path/URL of the file to be loaded.
7172
* @param {Function} onLoad - Executed when the loading process has been finished.
7273
* @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
@@ -97,6 +98,7 @@ class Loader {
9798
* This method needs to be implemented by all concrete loaders. It holds the
9899
* logic for parsing the asset into three.js entities.
99100
*
101+
* @abstract
100102
* @param {any} data - The data to parse.
101103
*/
102104
parse( /* data */ ) {}
@@ -171,6 +173,18 @@ class Loader {
171173

172174
}
173175

176+
/**
177+
* This method can be implemented in loaders for aborting ongoing requests.
178+
*
179+
* @abstract
180+
* @return {Loader} A reference to this instance.
181+
*/
182+
abort() {
183+
184+
return this;
185+
186+
}
187+
174188
}
175189

176190
/**

src/loaders/LoadingManager.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ class LoadingManager {
6969
*/
7070
this.onError = onError;
7171

72+
/**
73+
* Used for aborting ongoing requests in loaders using this manager.
74+
*
75+
* @type {AbortController}
76+
*/
77+
this.abortController = new AbortController();
78+
7279
/**
7380
* This should be called by any loader using the manager when the loader
7481
* starts loading an item.
@@ -269,6 +276,22 @@ class LoadingManager {
269276

270277
};
271278

279+
/**
280+
* Can be used to abort ongoing loading requests in loaders using this manager.
281+
* The abort only works if the loaders implement {@link Loader#abort} and `AbortSignal.any()`
282+
* is supported in the browser.
283+
*
284+
* @return {LoadingManager} A reference to this loading manager.
285+
*/
286+
this.abort = function () {
287+
288+
this.abortController.abort();
289+
this.abortController = new AbortController();
290+
291+
return this;
292+
293+
};
294+
272295
}
273296

274297
}

0 commit comments

Comments
 (0)