"Upon requesting three gltf files, the response was found to

Currently, I am utilizing the GLTF loader for the purpose of importing a custom model into my scene.

Within my codebase, there exists a class called Spaceship.js that manages the loading of the model.

// Spaceship.js

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

export default class Spaceship {
  constructor() {
    this.GLTFLoader = new GLTFLoader();

    this.loadModel(this.GLTFLoader, './spaceship_model.gltf').then(result => {
      this.model = result.scene;
    });
  }

  loadModel(loader, url) {
    return new Promise((resolve, reject) => {
      loader.load(
        url,

        gltf => {
          resolve(gltf);
        },

        undefined,

        error => {
          console.error('An error happened.', error);
          reject(error);
        }
      );
    });
  }
}

Additionally, there is a class called ThreeShell.js which serves as a container for the entire three.js scene.

import * as THREE from 'three';
import Spaceship from './Spaceship.js';

export default class ThreeShell {
  constructor(container = document.body) {
    this.container = container;
    this.setup();
  }

  setup() {
    ...

    this.spaceship = new Spaceship();
    console.log(this.spaceship);
    console.log(this.spaceship.model);

    ...
  }
}

Upon inspection, I discovered that when logging this.spaceship, an object with the model property is displayed. However, logging this.spaceship.model yields undefined.

https://i.sstatic.net/oHhH2.png

My suspicion is that this issue might be related to the handling of promises, an area in which I currently lack expertise. Hence, I am seeking your assistance in resolving this matter.

Answer №1

The GLTFLoader is designed to load assets asynchronously.

this.rocketShip = new RocketShip(); // Loading process initiates...
console.log(this.rocketShip);

// The "model" property doesn't exist yet as it's being accessed immediately, before the loading is complete
console.log(this.rocketShip.model);

If you wish to access the this.rocketShip.model, you must utilize the Promise outside the RocketShip class:

this.rocketShip = new RocketShip(); // Avoid loading in the constructor...
console.log(this.rocketShip);

// Trigger the load function here
this.rocketShip.loadModel().then((result) => {
    // Now the GLTF model will be available since you're waiting for the asynchronous callback
    console.log(result.scene);
});

It seems like you understand how Promises work, but if you need more clarity, you can refer to this explanation.

Answer №2

Marquizzo pointed out that the model loads asynchronously, making these lines ineffective:

    this.spaceship = new Spaceship();
    console.log(this.spaceship.model);

Fortunately, there are multiple solutions to this problem.

One approach is to include a wait function that returns the loading promise and utilize an async function to await it:

// Spaceship.js

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

export default class Spaceship {
  constructor() {
    this.GLTFLoader = new GLTFLoader();

    this._loadingPromise = this.loadModel(this.GLTFLoader, './spaceship_model.gltf').then(result => {
      this.model = result.scene;
    });
  }

  waitForLoad() {
    return this._loadingPromise;
  }

  loadModel(loader, url) {
    return new Promise((resolve, reject) => {
      loader.load(
        url,

        gltf => {
          resolve(gltf);
        },

        undefined,

        error => {
          console.error('An error occurred.', error);
          reject(error);
        }
      );
    });
  }
}

Then, in the setup:

import * as THREE from 'three';
import Spaceship from './Spaceship.js';

export default class ThreeShell {
  constructor(container = document.body) {
    this.container = container;
    this.setup();
  }

  async setup() {
    ...

    this.spaceship = new Spaceship();
    console.log(this.spaceship);
    await this.spaceship.waitForLoad();
    console.log(this.spaceship.model);

    ...
  }
}

This alternative approach is not necessarily superior or inferior, but simply demonstrates there are alternative methods without moving the loading process out of the constructor.

You can also achieve the desired outcome like so:

  setup() {
    ...

    this.spaceship = new Spaceship();
    console.log(this.spaceship);
    this.spaceship.waitForLoad().then(() => {
      console.log(this.spaceship.model);
    });

    ...
  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it true that Vue 3 + Inertia automatically removes event listeners upon component unmounting?

There is an event listener set up within the script setup block: <script setup> import {ref} from 'vue' const elementRef = ref(null) window.addEventListener('click', (event) => { if (!elementRef.value.contains(event.t ...

Unable to bind `this` using `call` method is not functioning as expected

Attempting to modify the Express app's .set function to be case-insensitive. For example, app.set('PORT',80); app.set('port'); // => undefined; aiming for it to return 80 Essentially, it's just a function that changes the ...

saving the hash key in a separate array

Currently, I have a collection of key-value pairs that need to be stored in another array. However, I am facing difficulties with the logic as I am unable to keep track of which keys-values have already been assigned while iterating over the list of object ...

What is the best way to manage Page Refresh using Angular.js?

I recently followed the tutorial at http://scotch.io/bar-talk/setting-up-a-mean-stack-single-page-application This guide went over controllers and services using angular.js for a single-page application. However, when I try to directly access /pageName o ...

Failure to retrieve blob - net::ERR_CONTENT_LENGTH_MISMATCH 200 (OK)

My fetch request code in my front end for a node js express web app hosted on MS Azure works well for small zip file blobs. However, it times out and displays the error net::ERR_CONTENT_LENGTH_MISMATCH 200 (OK) when dealing with large blobs. ...

Design an interactive div element that allows users to modify its content, by placing a span

Here is an example of the desired effect: ICON LINE - 1 This is some sample text inside a div element and the next line should begin here ICON LINE - 2 This is some sample text inside a div element a ...

Angular Typescript error: Trying to assign a value to 'someProperty' property of an undefined object

Within my Article class, I have a property called Image which is structured like this: export class Article { public image:Image; public images: Image[]; } If I decide to comment out this.article.image = new Image(); in the following way: constru ...

Enabling table row scrolling with keyboard navigation in React

Struggling to figure out how to make my table scroll while navigating through the rows using the onKeyDown event. It seems that the event isn't updating when using the keyboard, even though the highlighting of the selected row with selected is working ...

Using React to easily rearrange images by dragging and dropping them

Currently, I am working on incorporating drag-and-drop functionality using React JS along with the react-dropzone library to display thumbnails. The code implementation is provided below: import React from "react"; import ReactDOM from "react-dom"; impor ...

Retrieving status code without reliance on a back-end language (maybe through JavaScript?)

My new service offers a solution for error pages in web apps by providing a code snippet that can be easily copied and pasted into the error page templates, similar to Google Analytics. The status code is embedded in a hidden input within the installatio ...

What could be causing my Javascript prompts to not appear in my Express.IO .ejs file?

I am fairly new to JavaScript and exploring Node with Express.IO. I'm currently working on a project that involves tracking real-time connections made by different 'users' to the server. However, I've encountered an issue where my promp ...

I am looking to view all products that belong to the category with the ID specified in the request, and have red-colored stocks

Within my database, I have defined three mongoose models: Product, Category, and Stock. The Product model contains two arrays - categories and stocks, each including respective category and stock ids. My goal is to retrieve all products where the category_ ...

Numerous data retrieval commands within the componentWillMount lifecycle method

Initially, I utilized the componentWillMount() method to populate the articles property successfully by iterating over the values to display various images/text. However, I am now encountering an issue as I also need to use componentWillMount to populate ...

Can a layer be sliced to create a text-shaped cutout?

I want to achieve a cool text effect where the background is visible through the letters. I have explored options with background images and colors, but I haven't found any examples where the underlying layer is revealed. Is this even possible? Imag ...

I'm unsure about the JavaScript toolkit framework's handling of selecting HTML class attributes

I have been exploring the Electron Framework using a JavaScript toolkit known as Xel. In my main.js file, I am working with the following syntax: document.querySelector("menu.selected").className.remove('selected') In my Xel code snippet, I hav ...

Preventing pop-up windows from appearing when triggered by a mouse click event

I am looking for a solution to trigger a popup window when a user right-clicks on a specific area. Here is the current code I am using: $("#popup").bind('mousedown', function(e) { var w; if(e.which==3) { w=window.open('link& ...

Display toggle malfunctioning when switching tabs

I am currently working on implementing a search function with tabbed features. Everything seems to be displaying correctly without any errors. However, the issue arises when I try to click on any tab in order to show or hide specific content from other tab ...

Executing JavaScript code from an external link

Currently, I am in the process of developing a horizontal parallax website. The functionality is working seamlessly; when I click on the menu, the slides smoothly transition horizontally and display the corresponding content. However, I have encountered a ...

``I am encountering an issue where the highlighted color of a textbox is not being

In my MVC3 view page, I have a password control with an onblur function being called from the control itself: @Html.PasswordFor(m => m.CurrentPass, new Dictionary<string, object> { { "id", "txtCurrentPass" }, { "name", "CurrentPass" }, { "Class", ...

Passing data from an Express middleware to a Jade template

My KeystoneJS app is all set up, using Express and Jade. The default.jade file sets up a fullscreen background image along with various imports, the header, and footer of the site. I am attempting to rotate the image based on a selection of images stored ...