Gltf Loader order of execution issue

Hi There! I’m trying to understand how gltf loader works since I’m working on a small website prototype.
The idea was to import a single gltf that has 3 objects (3 emojis) and in the webpage have them change their position and rotation as the user scrolls.

The thing is, I can’t access my mesh’s properties nor edit them, as I just discovered, the gltf loader seems to be executing after all my other code has been called, so each emoji call outside the loader shows up as undefined. I though the code would execute from top to bottom (aside from function calls) But the gltf loader seems to be executing last.

How can I make it so that my script waits for my gltf model to be loaded before it keeps going with the other sections of the code?

import './style.css'
import * as THREE from 'three'
import * as dat from 'lil-gui'
import gsap from 'gsap'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { Audio, Scene } from 'three'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';

//console.log(THREE)

/**
 * Old Loaders
*/
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('/draco/')

const gltfLoader = new GLTFLoader()
gltfLoader.setDRACOLoader(dracoLoader)



/**
 * Debug
 */
const gui = new dat.GUI()
const debugObject = {}
const parameters = {
    materialColor: '#ffeded'
}
gui
    .addColor(parameters, 'materialColor')
    .onChange(() => {
        material.color.set(parameters.materialColor)
        particlesMaterial.color.set(parameters.materialColor)
    })

/**
 * Base
 */
// Canvas
const canvas = document.querySelector('canvas.webgl')

// Scene
const scene = new THREE.Scene()

/**
 * Objects
 */
// Texture
const textureLoader = new THREE.TextureLoader()
const gradientTexture = textureLoader.load('textures/gradients/3.jpg')
gradientTexture.magFilter = THREE.NearestFilter

// Material
const material = new THREE.MeshToonMaterial({
    color: parameters.materialColor,
    gradientMap: gradientTexture
})

/**
 * Models
 */

let mixer = null
const objectsDistance = 4

// prepare emoji (js) object
let emoji = {};
let loaded = false;




gltfLoader.load(
    'EMOJIS.gltf',
    (gltf) => {
        gltf.scene.scale.set(0.5, 0.5, 0.5)
        gltf.scene.position.set(0, 0, 0)
        scene.add(gltf.scene)

        // Animation
        mixer = new THREE.AnimationMixer(gltf.scene)

        gui.add(gltf.scene.position, 'y').min(-3).max(3).step(0.01).name('position y')
        gui.add(gltf.scene.position, 'x').min(-3).max(3).step(0.01).name('position x')
        gui.add(gltf.scene.position, 'z').min(-3).max(3).step(0.01).name('position z')

        //gltf.scene.children[2].material.roughness = 1

        gltf.scene.children[0].position.x = 2
        gltf.scene.children[1].position.x = - 2
        gltf.scene.children[2].position.x = 2

        gltf.scene.children[0].position.y = - objectsDistance * 0
        gltf.scene.children[1].y = - objectsDistance * 1
        gltf.scene.children[2].y = - objectsDistance * 2

        console.log("Emoji Inside Loader, Line 99")
        console.log(gltf.scene.children[0])

        /*
        var heart = gltf.scene.getObjectByName("heart", true);
        var heartEyes = gltf.scene.getObjectByName("heartEyes", true);
        var peach = gltf.scene.getObjectByName("peach", true); */

        // loop through all children and create a property 
        // for every child based on it's name
        gltf.scene.children.forEach((item) => {
            emoji[item.name] = item;
        })
        // then you can access every child through 
        // the named property of the shirt object

        console.log("emoji array")
        console.log(emoji.peach)
        console.log(emoji.heart)
        console.log(emoji.heart.rotation)
        console.log(emoji.heartEyes)
        loaded = true;


    }
)


console.log("Main scene")
console.log(scene)
console.log(scene.children)
console.log(scene.children[6])


console.log("Emoji outside of the loader, line 133?")
console.log(emoji)
console.log(emoji[heart])
console.log(emoji[0])
console.log(emoji.name[heart])
console.log("--- --- ---")

The calls of my emojis “outside” the loader all show as undefined because it is calling that part before actually loading the model, or so I would thin normally, but the debug line on 134, the console.log(emoji) just outside the loader shows my 3 geommetries inside this object array, so I don’t know what to think anymore, I’m very confused.

All help is very much appreciated.

hi @sarmak

Surely calling an object before load complete will give you undefined, as you guessed.

The gltf loader is started where it is in the code, but the callback is only executed at the end of the external resource loading.
So you have to keep this in mind and don’t call the resources until the end of the load (and you have the callback just to know when the load is finished)

it is strange that emoji is valued. Maybe it’s possible your emoji remained in the cache?

yes, its most likely the cache, thank you for your insight! It has proven to be very helpful.