Waiting for 3D Models to Load

I need help with implementing a method to wait for 3D models to be completely loaded.
For now this is all I have, these two methods in a class called World:

  _loadModelAndWait(gltfModelName) {
    return new Promise((resolve, reject) => {
      const loader = new GLTFLoader();
      let model;
      loader.load(`../models/${gltfModelName}.gltf`, (gltf) => {
        model = gltf.scene.children[0];
      }, undefined, (error) => {

  loadModel(gltfModelName) {
        .then((model) => {
          if (model) {
            console.log('Model loaded successfully!');
            model.scale.set(0.1,0.1,0.1); // I want to execute this outside the class
        .catch((error) => {

And it works, but I want to apply transformations to the objects outside the class, just like this:

const modelNames = ["3DModel1", "3DModel2"];
modelNames.forEach((model) => {myWorld.loadModel(model)});
console.log(myWorld.Objects.children[1]); //This should print the Object3D and not undefined
if(myWorld.Objects.children[1]) myWorld.Objects.children[1].scale.set(0.1, 0.1, 0.1);

Is there a clean way to handle this problem?

There’s like at least 100000 ways - but depends on the circumstances. If you just want to start applying transformations to the model, and not care if it’s loaded or not - just substitute it with a group:

const loadModel = (url) => {
  const group = new Three.Group();

  new Three.GLTFLoader().load(url, gltf => {

  return group;

const dolphinModel = loadModel('https://pbs.twimg.com/media/FFOjIvAUcAE9A5j.jpg');

// NOTE You can transform the model right away, let it load in the background in the meantime

dolphinModel.position.set(1.0, 1.0, 1.0);

This is a very simple and gentle solution for small projects - just remember you cannot access any contents of the actual model - so with the group approach, you can’t change materials, apply animations etc. until you’re sure the model is loaded.

If you’re looking for a production-ready solution for giant model-heavy projects - consider creating a sort of asynchronous preloading wrapper for models. Such wrapper should only start executing logic related to the model after the file is loaded and ready - that’ll also help you separate code responsibility nicely in the long term, ex.:

const gltfLoader = new Three.GLTFLoader();

class AsyncModelComponent {
  loop = null;

  constructor(props) {

  async init({ modelUrl, onFrame }) {
    if (modelUrl) {
      await this.loadModel(modelUrl);

    this.run({ onFrame });

  loadModel({ modelUrl }) {
    return new Promise(resolve => {
      gltfLoader.load(modelUrl, gltf => {
        this.model = gltf.scene;



  run({ onFrame }) {
    if (!onFrame) {

    const loopFn = () => {
      this.loop = requestAnimationFrame(() => loopFn());

      onFrame({ model: this.model });

    this.loop = loopFn();

  dispose() {
    // NOTE Dispose model and assets

    if (this.loop) {

// NOTE Then separately implement the logic for each model
new AsyncModelComponent({
  modelUrl: 'dolphin.glb',
  onFrame: (model) => {
    // NOTE You can be 100% sure the model is ready here

new AsyncModelComponent({
  modelUrl: 'dolphin2.glb',
  onFrame: (model) => {
    // NOTE Separate instance with independent logic
1 Like

Wow, that’s very helpful, thank you.
I don’t understand fully what the AsycModelComponent class is doing, since many of the things used are pretty new to me, but I get the general idea. I guess callback functions are problaly the solution I’m looking for. I’ll try my best to find an implementation that works best for my project!