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

JS/TS中await调用返回Promise的GLTF解析函数未生效问题排查

问题排查结论

你的代码无法正常返回结果是4个核心问题导致的:

  • 循环内部直接写return:遍历toAdd数组时只要碰到第一个类型为part的项,就会直接退出整个函数,后续所有项都不会处理;如果数组第一个元素不是part类型,循环走完后函数没有任何返回值,await拿到的是undefined,自然等不到异步结果。
  • 未处理GLTFLoader的错误分支:loader.parse方法第四个参数是错误回调,你没有传入,解析失败时既不会抛出错误也不会让Promise进入reject状态,会直接静默卡住。
  • 缺少类型与空值校验:你默认gltf.scene.children[0]一定是带geometry的Mesh对象,如果gltf结构存在嵌套、第一个子元素是Group分组而非Mesh,读取geometry属性时会直接抛错,且该错误未被Promise捕获,会导致Promise永远无法决议。
  • 未做批量异步等待:原逻辑只返回单个模型解析的Promise,没有等待所有part类型的模型全部解析完成,多模型场景下逻辑不完整。
修复后完整实现

parseGltfBlobs方法可直接替换原有代码:

public async parseGltfBlobs(toAdd: asmTreeNodeScene[]): Promise<void> {
    const loader = new GLTFLoader();
    // 收集所有待解析模型的异步任务
    const parseTasks: Promise<void>[] = [];

    for (let i = 0; i < toAdd.length; i++) {
        const componentId: number = toAdd[i].componentId;
        const isPart: boolean = toAdd[i].type == "part";
        
        if (isPart) {       
            const surfaceMeshKey: string = `${componentId}.${this.asmStateServ.decimation}`;
            // 提前校验缓存是否存在,避免读取null报错
            const meshCache = this.assemblyFetchServ.surfaceMeshesGltf.get(surfaceMeshKey);
            if (!meshCache?.gltfBytes) {
                console.warn(`未找到componentId为${componentId}的gltf缓存数据,跳过解析`);
                continue;
            }
            const gltfBytes = <ArrayBuffer>meshCache.gltfBytes;

            // 为每个模型创建独立解析任务,加入任务列表,不在循环内直接return
            const parseTask = new Promise<void>((resolve, reject) => {
                loader.parse(
                    gltfBytes,
                    "",
                    (gltf) => {
                        try {
                            // 递归查找场景中的Mesh,兼容Group嵌套结构
                            const findMesh = (obj: THREE.Object3D): THREE.Mesh | null => {
                                if ((obj as THREE.Mesh).isMesh) return obj as THREE.Mesh;
                                for (const child of obj.children) {
                                    const res = findMesh(child);
                                    if (res) return res;
                                }
                                return null;
                            };
                            const mesh = findMesh(gltf.scene);
                            if (!mesh) {
                                reject(new Error(`componentId为${componentId}的gltf中未找到有效Mesh对象`));
                                return;
                            }
                            if (!mesh.geometry.attributes.position || !mesh.geometry.index) {
                                reject(new Error(`componentId为${componentId}的Mesh缺少顶点或索引数据`));
                                return;
                            }

                            const vertices = mesh.geometry.attributes.position.array;
                            const faces = mesh.geometry.index.array;

                            const surfaceMesh = {
                                "component_id": componentId,
                                "vertices": vertices,
                                "faces": faces,
                            };
                            this.assemblyFetchServ.surfaceMeshes.set(surfaceMeshKey, surfaceMesh);
                            console.log(`已存储componentId为${componentId}的网格数据`);
                            resolve();
                        } catch (err) {
                            reject(err);
                        }
                    },
                    // 传入解析错误回调
                    (err) => {
                        reject(new Error(`解析componentId为${componentId}的gltf失败: ${err?.message || err}`));
                    }
                );
            });
            parseTasks.push(parseTask);
        }
    }

    // 等待所有解析任务完成,任意任务失败会抛出对应错误
    await Promise.all(parseTasks);
}

调用部分补充错误捕获即可,原有逻辑无需大改:

this.requestMissingResources(toAdd, this.isGLTF).subscribe(
    () => {},
    (err) => {
        console.log(err);
    },
    async () => {
        if(this.isGLTF) {
            console.log("开始解析gltf数据");
            try {
                await this.parseGltfBlobs(toAdd);
                console.log("所有gltf数据解析完成");
                // 此处写解析完成后需要执行的后续业务逻辑
            } catch (parseErr) {
                console.error("gltf解析流程出错:", parseErr);
            }
        }
    }
)

内容的提问来源于stack exchange,提问作者GeekAndNerd223

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:09:10