@hkdigital/lib-core 0.4.77 → 0.4.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -380,31 +380,43 @@ export default class SceneBase {
380
380
  return;
381
381
  }
382
382
 
383
- // Start all loaders
383
+ let completedCount = 0;
384
+ const totalLoaders = this.sources.length;
385
+
386
+ // Start all loaders with completion callbacks
384
387
  for (let i = 0; i < this.sources.length; i++) {
385
388
  const source = this.sources[i];
386
389
  const loader = this.getLoaderFromSource(source);
387
- loader.load();
388
- }
389
390
 
390
- // Check if all loaders have already completed synchronously (e.g., from cache)
391
- setTimeout(() => {
392
- if (this.#state.current === STATE_LOADING) {
393
- let allLoaded = true;
394
- for (const source of this.sources) {
395
- const loader = this.getLoaderFromSource(source);
396
- if (loader.state !== STATE_LOADED) {
397
- allLoaded = false;
398
- break;
399
- }
391
+ loader.load((completedLoader, finalState) => {
392
+ console.debug(`SceneBase:loader-finished [${completedLoader._url}] ${finalState}`);
393
+
394
+ // Check for errors
395
+ if (finalState === STATE_ERROR) {
396
+ this.#state.send(ERROR, completedLoader.error || new Error('Loader failed'));
397
+ return;
400
398
  }
401
399
 
402
- if (allLoaded) {
403
- console.debug('SceneBase:all-loaders-already-loaded, sending LOADED');
404
- this.#state.send(LOADED);
400
+ // Check for abort - don't count aborted loaders as completed
401
+ if (finalState === STATE_ABORTED) {
402
+ // Aborted loaders are handled by SceneBase's own abort logic
403
+ console.debug(`SceneBase:loader-aborted [${completedLoader._url}] - not counting toward completion`);
404
+ return;
405
405
  }
406
- }
407
- }, 0);
406
+
407
+ // Only count successfully loaded loaders
408
+ if (finalState === STATE_LOADED) {
409
+ completedCount++;
410
+ console.debug(`SceneBase:loader-completed [${completedLoader._url}] (${completedCount}/${totalLoaders})`);
411
+
412
+ // Check for completion
413
+ if (completedCount === totalLoaders) {
414
+ console.debug('SceneBase:all-loaders-completed-via-callback');
415
+ this.#state.send(LOADED);
416
+ }
417
+ }
418
+ });
419
+ }
408
420
  }
409
421
 
410
422
  #startAbort() {
@@ -35,8 +35,11 @@ export default class NetworkLoader {
35
35
  _abortLoading: null | (() => void);
36
36
  /**
37
37
  * Start loading all network data
38
+ *
39
+ * @param {null|((loader: NetworkLoader, finalState: string) => void)} [onCompletion]
40
+ * Optional callback called when loader reaches a terminal state (loaded/error/aborted)
38
41
  */
39
- load(): void;
42
+ load(onCompletion?: null | ((loader: NetworkLoader, finalState: string) => void)): void;
40
43
  /**
41
44
  * Unoad all network data
42
45
  */
@@ -8,6 +8,8 @@ import {
8
8
  STATE_UNLOADING,
9
9
  STATE_LOADED,
10
10
  STATE_ABORTING,
11
+ STATE_ABORTED,
12
+ STATE_ERROR,
11
13
  LOAD,
12
14
  ERROR,
13
15
  LOADED,
@@ -89,6 +91,9 @@ export default class NetworkLoader {
89
91
  /** @type {null|(()=>void)} */
90
92
  _abortLoading = null;
91
93
 
94
+ /** @type {null|((loader: NetworkLoader, finalState: string) => void)} */
95
+ #completionCallback = null;
96
+
92
97
  /**
93
98
  * Construct NetworkLoader
94
99
  *
@@ -104,6 +109,17 @@ export default class NetworkLoader {
104
109
  console.debug(`loader:onenter [${this._url}] ${currentState}`);
105
110
  this.state = currentState;
106
111
 
112
+ // Check if we've reached a terminal state
113
+ const isTerminalState = currentState === STATE_LOADED ||
114
+ currentState === STATE_ERROR ||
115
+ currentState === STATE_ABORTED;
116
+
117
+ if (isTerminalState && this.#completionCallback) {
118
+ const callback = this.#completionCallback;
119
+ this.#completionCallback = null; // Clean up immediately
120
+ callback(this, currentState); // Call with loader and final state
121
+ }
122
+
107
123
  switch (currentState) {
108
124
  case STATE_LOADING:
109
125
  {
@@ -155,8 +171,12 @@ export default class NetworkLoader {
155
171
 
156
172
  /**
157
173
  * Start loading all network data
174
+ *
175
+ * @param {null|((loader: NetworkLoader, finalState: string) => void)} [onCompletion]
176
+ * Optional callback called when loader reaches a terminal state (loaded/error/aborted)
158
177
  */
159
- load() {
178
+ load(onCompletion = null) {
179
+ this.#completionCallback = onCompletion;
160
180
  this.#state.send(LOAD);
161
181
  }
162
182
 
@@ -327,6 +347,12 @@ export default class NetworkLoader {
327
347
  // this._size = this._buffer.byteLength;
328
348
  // }
329
349
 
350
+ // Check if we've been aborted before sending LOADED
351
+ if (this.#state.current === STATE_ABORTING || this.#state.current === STATE_ABORTED) {
352
+ console.debug(`loader:already-aborted [${this._url}] - not sending LOADED`);
353
+ return;
354
+ }
355
+
330
356
  console.debug(`loader:sending-LOADED [${this._url}]`);
331
357
  this.#state.send(LOADED);
332
358
  } catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hkdigital/lib-core",
3
- "version": "0.4.77",
3
+ "version": "0.4.78",
4
4
  "author": {
5
5
  "name": "HKdigital",
6
6
  "url": "https://hkdigital.nl"