Error 'Uncaught (in promise) TypeError: duck is undefined' - multiple gltf models

Dear three.js knowing people,
Below you can see my very first code. I would like to build a website with four different rotating gltf models. Each of them should be a hyperlink. At least this is my dream. So far I managed somehow to load two of them and let them rotate in the live server. But I’m stuck with this error ‘Uncaught (in promise) TypeError: duck is undefined’.
How can I solve this problem? I also would appreciate your help for creating the links.
THANK YOU!

let container;
let camera;
let renderer;
let scene;
let box;
let duck;
let controls;

function init(){
    container = document.querySelector('.scene');

   
    scene = new THREE.Scene();

    const fov = 10;
    const aspect = container.clientWidth / container.clientHeight;
    const near = 0.1;
    const far = 900;


    camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
    camera.position.set(0, 30, 1);


    const ambient = new THREE.AmbientLight(0x404040, 3);
    scene.add(ambient);

    const light = new THREE.DirectionalLight(0xffffff, 0.5);
    light.position.set(10,10,30);
    scene.add(light);
    
    renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    renderer.setSize(container.clientWidth, container.clientHeight);
    renderer.setPixelRatio(window.devicePixelRatio);

    container.appendChild(renderer.domElement);

   
    controls = new THREE.OrbitControls (camera, renderer.domElement);
    
    let loader = new THREE.GLTFLoader();
    
    loader.load('./3d/duck.gltf', function(gltf){
        scene.add(gltf.scene);
        duck = gltf.scene.children[0];
        duck.position.set(0,0,0);
        animate();
    })

    loader.load('./3d/cube.gltf', function(gltf){
        scene.add(gltf.scene);
        box = gltf.scene.children[0];
        box.position.set(-2,0,0);
        animate();
    })

    
}

function animate(){
    controls.update();
    duck.rotation.x += 0.01
    box.rotation.y += 0.01
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}


init();


function onWindowResize () {
    camera.aspect = container.clientWidth / container.clientHeight;
    camera.updateProjectionMatrix();

    renderer.setSize(container.clientWidth, container.clientHeight);
}

    window.addEventListener('resize', onWindowResize);

There are quite a few ways to solve it - a dirty, but quick solution would be to just put the variables inside animate() inside conditionals:

function animate() {
  if (duck) {
    duck.rotation.x += 0.01;
  }

  // ... Rest of the code
}

(And a bit more clean way, would be to call animate only after all the models are loaded - not after each model is loaded separately.)

1 Like

Promise.all()
you can use this to promise your async function finished to animate