Gltf file loaded twice when loading is initiated in LoadingManager() inside onProgress callback

I have two glb files, loadingScene.glb and mainScene.glb. The loadingScene.glb file consists of three meshes- text, a plane(to receive shadows), and a cactus that I’m using as part of a loading screen displayed to the user, while the mainScene.glb and all of its associated assets are still loading. In order to indicate the loading progress, I wanted to have a little fun and have a shadow shift from the left to the right to suggest the current loading progress(pictured below).

Therefore, I needed the loadingScene.glb file to load first, then after, I load the mainScene.glb content. I achieved this in the THREE.LoadingManager() onProgress callback by checking for when itemUrl==="./loadingScene.glb", indicating that, that file has been loaded, then calling a loadMainScene() function which then loads the mainScene.glb. However, when I added a console.log("itemUrl", itemUrl) inside of the onProgress callback, I see ./mainScene.glb multiple times, indicating that it is loading more than once. Why is this?

import * as THREE from "three"
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader.js"
import {RGBELoader} from "three/examples/jsm/loaders/RGBELoader.js"
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls.js"

const gScene = new THREE.Scene()
const canvas = document.querySelector("#c")
const gCamera = new THREE.PerspectiveCamera(50, canvas.clientWidth/canvas.clientHeight, 0.1, 1000)
const gRenderer = new THREE.WebGLRenderer({canvas, alpha: true, antialias: true})
gRenderer.setPixelRatio( window.devicePixelRatio );
gRenderer.setSize( window.innerWidth, window.innerHeight );
gRenderer.toneMapping = THREE.ACESFilmicToneMapping;
gRenderer.shadowMap.enabled = true
gRenderer.toneMappingExposure = 1;
gRenderer.outputEncoding = THREE.sRGBEncoding;

gCamera.position.x = 24
gCamera.position.y = 123
gCamera.position.z = 0

const loadingManager = new THREE.LoadingManager(

    () => {


    },

    (itemUrl, itemsLoaded, itemsTotal) => 
    {
        console.log("itemUrl", itemUrl)

        if(itemUrl === "./loadingScene.glb"){
            loadMainScene()

        }

        let loadedRatio = itemsLoaded / itemsTotal
        if(directionalLight.position.z < 30){
            directionalLight.position.set(-20, 130, -30 + (60 * loadedRatio))

        }
    }
)

const gltfLoader = new GLTFLoader(loadingManager)


function loadMainScene(){
    gltfLoader.load('./mainScene.glb', (glb) => {    
    })
}

const controls = new OrbitControls(gCamera, canvas)
controls.target.set(0,0,0)
controls.update()

const directionalLight = new THREE.DirectionalLight(0xffffff, 5)
directionalLight.castShadow =  true

directionalLight.position.set(-10, 130, -30)
directionalLight.target.position.set(7.5, 115,0)
directionalLight.shadow.camera['left'] = -15
directionalLight.shadow.camera['right'] = 15
directionalLight.shadow.camera['bottom'] = -15
directionalLight.shadow.camera['top'] = 15
directionalLight.shadow.mapSize.width = 1024
directionalLight.shadow.mapSize.height = 1024
directionalLight.shadow.camera.updateProjectionMatrix();
gScene.add(directionalLight)
gScene.add(directionalLight.target)
gCamera.lookAt(7.5,115,0)

gltfLoader.load('./loadingScene.glb', (glb) => {    
        glb.scene.traverse((child) => {      
                if(child.isMesh){             
                    if(child.name.toLowerCase().includes('backdrop')){
                        child.material = new THREE.ShadowMaterial()
                        child.receiveShadow = true
                    }

                    else if(child.name.toLowerCase().includes("saguaro")){
                        child.material =  new THREE.MeshBasicMaterial({color:0x000000})
                        child.castShadow = true
                    }
                    else{
                        child.material = new THREE.MeshBasicMaterial({color:0x1a1004})
                        child.castShadow = true
                    }                  
                }
        })
        gScene.add(glb.scene)
})

window.addEventListener('resize', onWindowResize)
function onWindowResize(){
    gCamera.aspect = window.innerWidth / window.innerHeight
    gCamera.updateProjectionMatrix()
    gRenderer.setSize(window.innerWidth, window.innerHeight)
}

function render(){
    gRenderer.render(gScene,gCamera)
    requestAnimationFrame(render)
}
requestAnimationFrame(render)

When combining LoadingManager with GLTFLoader there is a non-obvious restriction. The manager tracks for each glTF assets an additional item to make sure onLoad() is correctly fired. Unfortunately, this produces an incorrect item count and a confusing progress report.

As a workaround, I suggest you are not using LoadingManager for triggering the second loading process. Instead use something like:

const gltf = await gltfLoader.loadAsync( './loadingScene.glb' );
loadMainScene();