引入资源
import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
loadModel(option) {
console.log("option1", option);
let model = null;
const loader1 = new GLTFLoader();
console.log("loader1", loader1);
loader1.load(option.url, (gltf) => {
model = gltf.scene;
model.position.set(option.x, option.y, option.z);
// 模型中添加
this.scene.add(gltf.scene);
});
console.log("model1111", model);
return model;
},
使用
let option = {
url: "./model/CesiumAir/Cesium_Air.glb",
x: 15,
y: 5,
z: 0,
};
ffThree.loadModel(option);
异步加载
GLTFLoader
的load
方法是异步的,意味着它会在加载完成前立即返回,并且不会阻塞后续代码的执行。因此,当你在加载完成前访问model
变量时,它仍然是null
,因为加载过程尚未完成。
执行顺序问题
让我们来分析一下你的代码执行顺序:
-
创建loader1实例:
const loader1 = new GLTFLoader();
-
调用loader1.load():
loader1.load(option.url, (gltf) => {...});
- 此时,
loader1.load
开始加载模型,但是它是异步操作,会立即返回,继续执行后续代码。
- 此时,
-
打印model变量:
console.log("model1111", model);
- 在加载完成之前,这行代码会打印
model1111 null
,因为model
还没有被赋值。
- 在加载完成之前,这行代码会打印
-
返回model:
return model;
- 函数会立即返回
null
,因为model
还没有被赋值为加载完成的模型。
- 函数会立即返回
使用Promise对象
一种常见的方法是利用Promise对象或者回调函数来处理异步加载的结果。例如,可以修改你的函数,使其返回一个Promise对象,当模型加载完成时,Promise对象resolve模型对象。
loadModelPromise(option) {
return new Promise((resolve, reject) => {
const loader1 = new GLTFLoader();
loader1.load(
option.url,
(gltf) => {
const model = gltf.scene;
model.position.set(option.x, option.y, option.z);
this.scene.add(model);
resolve(model); // 将加载的模型传递给Promise的resolve函数
},
undefined,
reject
);
});
},
-
loadModel
函数现在返回一个Promise对象,当模型加载成功后,Promise会resolve为加载的模型对象。 - 在加载成功的回调函数中,我们通过调用
resolve(model)
来传递加载的模型对象。
使用
let option = {
url: "./model/CesiumAir/Cesium_Air.glb",
x: -15,
y: 5,
z: 0,
};
loadModelPromise(option).then((res) => {
console.log("得到加载的glb模型,可以在这对其修改", res);
// res.scale.set(0.1, 0.1, 0.1);
});
效果