Can't re-load obj once it's been aborted

I have a drop-down where the user can select different scenes (.obj with their .mtl) to load, which works great, but if the user selects a new scene while still loading a previously selected one, I gotta abort the previous loading process to start a new one or else I would be loading 2 .obj simultaneously, which is obviously not desired, and this works. I abort the xhr.currentTarget before loading the new one and it successfully loads the newly selected scene, but my problem is that now the scene that had it’s loading process aborted will not load whatsoever.

So, if I select item A from the drop-down, then while loading I select item B it begins loading item B (it could finish loading or I could interrupt it as well), and if I click back to item A the .obj won’t load, thou the .mtl does (same for item B if its loading process was aborted as well)… here’s the code:

const xhrCurrentTarget;
loadScene() {
      const {
         TJSsetup,
         sceneMounted,
         selectedScene,
         isSceneLoading,
         sceneLoadingError
      } = this.state;
      const { userData } = this.props;

      const userId = userData._id;

      const { THREE } = window;

      console.log('isSceneLoading: ', isSceneLoading);
      if (isSceneLoading) {
         xhrCurrentTarget.abort();

        // this did nothing
         xhrCurrentTarget = null;
      }

      // Check if there was a scene loaded
      console.log('TJSsetup: ', TJSsetup);
      if (TJSsetup) {
         this.clear({ loadScene: true });
         return;
      }

      this.TJSquickSetup();
      this.start();

      this.enableOrbitControls({ lookAtX: 0, lookAtY: 0, lookAtZ: 0 });

      // GET .OBJ AND .MTL URL
      const dns = "http://myDNS";
      let renderPath = `${dns}/${userId}/${selectedScene._id}/`;

      let objUrl = `${selectedScene.name}.obj`;
      let mtlUrl = `${selectedScene.name}.mtl`;

      const mtlLoader = new THREE.MTLLoader();
      mtlLoader.setPath(renderPath);
      mtlLoader.setCrossOrigin(true);

      // MTL LOADER FUNCTIONS

      const MTLonLoad = materials => {
         materials.preload();
         const objLoader = new THREE.OBJLoader();
         objLoader.setMaterials(materials);
         objLoader.setPath(renderPath);

         console.log('objUrl: ', objUrl);
         console.log('objLoader: ', objLoader);
    
         // here's where everything 'stops' if the .obj was previously aborted
        // so below here it doesn't run, I know it because I can't even console.log
        // the loading progress of the .obj, which means the .mtl did load
         objLoader.load(
            objUrl,
            OBJonLoad.bind(this),
            OBJonProgress.bind(this),
            OBJonError.bind(this)
         );
      };

      const MTLonProgress = xhr => {
         this.setState({ isSceneLoading: true, sceneLoadingError: "" });
      };

      const MTLonError = sceneLoadingError => {
         const loadingProgress = null;
         sceneLoadingError = `
         Email: ${userData.email.value} --
         sid: ${selectedScene._id} --
         On: .mtl --
         Status: ${
            sceneLoadingError.currentTarget.status
         } --
         Mssg: ${sceneLoadingError.currentTarget.statusText}`;

         this.setState({
            loadingProgress,
            sceneLoadingError,
            isSceneLoading: false,
            displayMode: "raw"
         });
      };

      // OBJ LOADER FUNCTIONS
      const OBJonProgress = xhr => {
            console.log('xhr: ', xhr);
         const loadingProgress = Math.round((xhr.loaded / xhr.total) * 100);
         xhrCurrentTarget = xhr.currentTarget;

         this.setState({
            loadingProgress,
            sceneLoadingError: ""
         });
      };

      const OBJonError = sceneLoadingError => {
         const loadingProgress = null;
         sceneLoadingError = `
         Email: ${userData.email.value} --
         sid: ${selectedScene._id} --
         On: .obj --
         Status: ${
            sceneLoadingError.currentTarget.status
         } --
         Mssg: ${sceneLoadingError.currentTarget.statusText}`;

         this.setState({
            loadingProgress,
            sceneLoadingError,
            isSceneLoading: false,
            displayMode: "raw"
         });
      };

      const OBJonLoad = object => {
         // Disable loading feedback
         const loadingProgress = 0;

         object.name = "userLoadedScene";
         object.position.set(0, 0, 0);
         var material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
         object.traverse(function(child) {
            if (
               child instanceof THREE.Mesh
            ) {
               child.material = material;
            }
         });

         this.scene.add(object);
         if (!sceneMounted) {
            this.mount.appendChild(this.renderer.domElement);
            this.setEventListeners();
            this.setPostProcessing();
         }
         this.setState({
            loadingProgress,
            sceneLoadingError: "",
            sceneMounted: true,
            isSceneLoading: false
         });
      };      

      mtlLoader.load(
         mtlUrl,
         MTLonLoad.bind(this),
         MTLonProgress.bind(this),
         MTLonError.bind(this)
      );
   }

   clear({ loadScene }) {
      const { eventListenersSet } = this.state;
      this.stop();
      // Clear object name from form
      var selectedObject = this.scene.getObjectByName("userLoadedScene");

      if (eventListenersSet) {
         window.removeEventListener("resize", this.onWindowResize, false);
         window.removeEventListener("mousemove", this.onTouchMove);
         window.removeEventListener("touchmove", this.onTouchMove);
         window.removeEventListener("click", this.onObjectClick);
      }

      if (this.mount && this.renderer) {
         if (this.renderer.domElement.parentNode === this.mount) {
            this.mount.removeChild(this.renderer.domElement);
         }
      }

      this.controls && this.controls.dispose();
      this.scene && this.scene.remove(selectedObject);
      this.TJSreset();

      this.setState(
         {
            clickedPlacement: {},
            sceneMounted: false,
            eventListenersSet: false,
            postProcessingSet: false,
            sceneLoadingError: "",
            isSceneLoading: false
         },
         () => {
            loadScene && this.loadScene();
         }
      );
   }

Note: don’t mind much about the TSJsetup, the problem is that for some reason on the MTLonLoad function objLoader.load() won’t work if the object’s been aborted before.

here’s the network tab, see how the scecond time the object A is beign loaded, the .obj is not even fetched.

Screenshot_1

Does it work if you activate the checkbox “Disable cache” in Chrome dev tools?

BTW: Perform the reload of your app with opened dev tools otherwise the setting is not active.

image

Hey, sorry for the delayed answer, didn’t get the notification.
I managed a workaround, I’m adding a timestamp to the objUrl variable if the obj load was aborted, additionally, I am saving those timestamps if the obj was fully loaded so I can do a quick reload using cache, although it still doesn’t explain why I had to do this.

Here’s the new code:

loadScene() {
      const { xhrCurrentTarget } = this;
      const {
         TJSsetup,
         sceneMounted,
         selectedScene,
         isSceneLoading
      } = this.state;
      const { userData } = this.props;

      const { THREE } = window;

      const userId = userData._id;

      if (isSceneLoading) {
         xhrCurrentTarget.abort();
         this.abortedObjs[this.lastObjURL] = "Not loaded";
      }

      // Check if there was a scene loaded
      if (TJSsetup) {
         this.clear({ loadScene: true });
         return;
      }

      this.TJSquickSetup();
      this.start();

      this.enableOrbitControls({ lookAtX: 0, lookAtY: 0, lookAtZ: 0 });

      // GET .OBJ AND .MTL URL
      const dns = "myDNS";
      let renderPath = `${dns}/${userId}/${selectedScene._id}/`;

      let objTimestamp = Date.now();

      let objUrl = `${selectedScene.name}.obj`;
      const objUrlWithoutTimestamp = objUrl;
      let mtlUrl = `${selectedScene.name}.mtl`;

      if (this.abortedObjs[objUrlWithoutTimestamp]) {
         if (this.abortedObjs[objUrl] === "Not loaded") {
            // new timestamp for fetching a 'new' url
            objUrl += `?${objTimestamp}`;
         } else {
            // if the obj was once aborted but its value is a string, then that's the timesptamp that was used for fully load (the second time the object was attempted to load)
            objUrl += `?${this.abortedObjs[objUrlWithoutTimestamp]}`;
         }
      }

      this.lastObjURL = objUrlWithoutTimestamp;

      const mtlLoader = new THREE.MTLLoader();
      mtlLoader.setPath(renderPath);
      mtlLoader.setCrossOrigin(true);

      // MTL LOADER FUNCTIONS

      const MTLonLoad = materials => {
         materials.preload();
         const objLoader = new THREE.OBJLoader();
         objLoader.setMaterials(materials);
         objLoader.setPath(renderPath);

         objLoader.load(
            objUrl,
            OBJonLoad.bind(this),
            OBJonProgress.bind(this),
            OBJonError.bind(this)
         );
      };

      const MTLonProgress = xhr => {
         this.setState({ isSceneLoading: true, sceneLoadingError: "" });
      };

      const MTLonError = sceneLoadingError => {
         const loadingProgress = null;
         sceneLoadingError = `
         Email: ${userData.email.value} --
         sid: ${selectedScene._id} --
         On: .mtl --
         Status: ${sceneLoadingError.currentTarget.status} --
         Mssg: ${sceneLoadingError.currentTarget.statusText}`;

         this.setState({
            loadingProgress,
            sceneLoadingError,
            isSceneLoading: false,
            displayMode: "raw"
         });
      };

      // OBJ LOADER FUNCTIONS
      const OBJonProgress = xhr => {
         const loadingProgress = Math.round((xhr.loaded / xhr.total) * 100);
         this.xhrCurrentTarget = xhr.currentTarget;

         this.setState({
            loadingProgress,
            sceneLoadingError: ""
         });
      };

      const OBJonError = sceneLoadingError => {
         const loadingProgress = null;
         sceneLoadingError = `
         Email: ${userData.email.value} --
         sid: ${selectedScene._id} --
         On: .obj --
         Status: ${sceneLoadingError.currentTarget.status} --
         Mssg: ${sceneLoadingError.currentTarget.statusText}`;

         this.setState({
            loadingProgress,
            sceneLoadingError,
            isSceneLoading: false,
            displayMode: "raw"
         });
      };

      const OBJonLoad = object => {
         // Disable loading feedback
         const loadingProgress = 0;

         object.name = "userLoadedScene";
         object.position.set(0, 0, 0);
         var material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
         object.traverse(function(child) {
            if (
               child instanceof THREE.Mesh &&
               child.name.includes(ADMIX_OBJ_PREFIX)
            ) {
               child.material = material;
            }
         });

         this.scene.add(object);

         if (!sceneMounted) {
            this.mount && this.mount.appendChild(this.renderer.domElement);
            this.setEventListeners();
            this.setPostProcessing();
         }

         if (this.abortedObjs[objUrlWithoutTimestamp]) {
            // if the obj was finally let to load, store the timestamp for quick load using cache
            this.abortedObjs[objUrlWithoutTimestamp] = objTimestamp;
         }

         this.setState({
            loadingProgress,
            sceneLoadingError: "",
            sceneMounted: true,
            isSceneLoading: false
         });
      };

      mtlLoader.load(
         mtlUrl,
         MTLonLoad.bind(this),
         MTLonProgress.bind(this),
         MTLonError.bind(this)
      );
   }

clear({ loadScene }) {
      const { eventListenersSet } = this.state;
      this.stop();
      // Clear object name from form
      var selectedObject = this.scene.getObjectByName("userLoadedScene");

      if (eventListenersSet) {
         window.removeEventListener("resize", this.onWindowResize, false);
         window.removeEventListener("mousemove", this.onTouchMove);
         window.removeEventListener("touchmove", this.onTouchMove);
         window.removeEventListener("click", this.onObjectClick);
      }

      if (this.mount && this.renderer) {
         if (this.renderer.domElement.parentNode === this.mount) {
            this.mount.removeChild(this.renderer.domElement);
         }
      }

      this.controls && this.controls.dispose();
      this.scene && this.scene.remove(selectedObject);
      this.TJSreset();

      this.setState(
         {
            clickedPlacement: {},
            sceneMounted: false,
            eventListenersSet: false,
            postProcessingSet: false,
            sceneLoadingError: "",
            isSceneLoading: false
         },
         () => {
            loadScene && this.loadScene();
         }
      );
   }