使用Promise与Three.js导入3D模型的异步问题求助
问题解决:等待所有3D模型加载完成后触发Promise resolve
核心思路
要实现所有模型加载完成后再resolve主Promise,需要把每个模型的加载过程包装成Promise,用Promise.all()监听所有模型加载完成的信号,再结合主Promise逻辑完成触发。
具体修改步骤
1. 改造body函数,返回Promise包装模型加载过程
把GLTFLoader的异步加载逻辑包裹在Promise中,加载成功时resolve,失败时reject:
function body(scene, world, bodyType, colliderType, dimension, translation, rotation) { return new Promise((resolve, reject) => { new GLTFLoader_js_1.GLTFLoader().load( `src/models/${colliderType}.glb`, function (gltf) { var model = gltf.scene; collider = gltf.scene; model.scale.x = dimension.hx; model.scale.y = dimension.hy; model.scale.z = dimension.hz; model.traverse(function (object) { if (object.isMesh) object.castShadow = true; }); model.position.x = translation.x; model.position.y = translation.y; model.position.z = translation.z; model.rotation.x = rotation.x; model.rotation.y = rotation.y; model.rotation.z = rotation.z; scene.add(model); var gltfAnimations = gltf.animations; var mixer = new THREE.AnimationMixer(model); var animationsMap = new Map(); gltfAnimations .filter(function (a) { return a.name != "TPose"; }) .forEach(function (a) { animationsMap.set(a.name, mixer.clipAction(a)); }); // 模型加载完成,触发resolve resolve(model); }, // 加载失败时触发reject undefined, function (error) { console.error(`模型${colliderType}加载失败`, error); reject(error); } ); }); }
2. 改造generateContent函数,收集所有模型加载Promise
让generateContent返回一个Promise,用Promise.all()等待所有模型加载完成,同时可兼容其他耗时操作:
function generateContent() { const modelPromises = []; var arrow3 = body(scene, world, 'static', 'arrow', { hx: 0.2, hy: 0.2, hz: 0.2 }, { x: 34.5, y: 3.35, z: 6 }, { x: 0, y:11, z: 0}); modelPromises.push(arrow3); bodys.push(arrow3); var phone = body(scene, world, 'static', 'phone', { hx: 1.3, hy: 1.3, hz: 1.3 }, { x: 35.35, y:1.8, z: 6.5 }, { x: 0, y:0, z: 0}); modelPromises.push(phone); bodys.push(phone); var pencil = body(scene, world, 'static', 'pencil', { hx: 2, hy: 2, hz: 2 }, { x: 35.5, y:1.8, z: 14 }, { x: 0, y:11, z: 0}); modelPromises.push(pencil); bodys.push(pencil); // 若有其他异步耗时操作,可包装成Promise加入数组 // const otherTasks = [otherAsyncOperation()]; // return Promise.all([...modelPromises, ...otherTasks]); // 等待所有模型加载完成 return Promise.all(modelPromises); }
3. 改造主Promise逻辑,等待所有任务完成后触发resolve
让主Promise等待generateContent()的结果,再执行自定义条件判断:
const myGeneralAsyncPromise = new Promise((res, rej) => { generateContent() .then(() => { // 模型全部加载完成后,执行你的条件判断 if (/* 自定义判断条件 */) { res(); } else { rej(); } }) .catch((error) => { // 任一模型加载失败,触发reject rej(error); }); }); myGeneralAsyncPromise.then(allIsReady, notReadyYet);
关键说明
GLTFLoader.load()是异步操作,必须包装成Promise才能被Promise.all()监听加载完成状态。Promise.all()会等待所有子Promise都resolve后才返回成功结果,只要有一个子Promise失败就会立即触发失败,确保所有模型都加载成功才继续后续流程。- 若
generateContent()中有同步耗时操作,可直接放在Promise.all()前执行;异步操作则同样包装成Promise加入数组即可。
内容的提问来源于stack exchange,提问作者pocketGod123
相关产品推荐
相关产品推荐

