You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 22:57:26