Angular中创建Observable获取GLTF格式表面网格数据的正确实现
GLTF接口方法实现修正
你原有实现存在几处语法和逻辑错误,以下是可直接运行的正确版本,同时明确GLTFLoader的使用规则。
原有代码问题清单
- fetch配置错误:
responseType不属于fetch请求头字段,放在headers中属于无效配置,获取二进制响应直接调用response.arrayBuffer()即可 - Promise链式调用括号嵌套错误,容易导致异常无法被正常捕获
- GLTFLoader回调参数错误:成功回调中传入了未定义的
surfaceMesh变量,实际解析结果是回调的入参gltf对象,且未处理GLTF解析阶段的错误 - RxJS操作符使用不当:
map用于转换流数据,写入缓存属于副作用操作,用map会导致流返回值为undefined,下游订阅拿不到数据 - 缺少fetch响应状态校验,服务端返回404/500等错误时会进入错误的解析流程
完整正确实现
// 提前导入所需依赖 // import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; // import { Observable, of } from 'rxjs'; // import { tap } from 'rxjs/operators'; public getSurfaceMeshGLTF(componentId: number, decimate: number): Observable<any> { const activeUrl = new URL(this.serverAddress); const surfaceMeshKey: string = `${componentId}.${decimate}`; // 缓存命中直接返回,避免重复请求 if (this.surfaceMeshes.has(surfaceMeshKey)) { return of(this.surfaceMeshes.get(surfaceMeshKey)); } const targetUrl = new URL(`${activeUrl.origin}${environment.apiBasePath}/surface_mesh_gltf/${componentId}?decimate=${decimate}`); const params: { [name: string]: string } = {}; if (this.customLookupAddress) { params.lookup = this.customLookupAddress; } if (this.customGatewayAddress) { params.gateway = this.customGatewayAddress; } Object.keys(params).forEach(key => targetUrl.searchParams.append(key, params[key])); const data$ = new Observable(observer => { fetch(targetUrl.toString(), { method: 'GET' }) .then(response => { if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } return response.arrayBuffer(); }) .then(arrayBuffer => { const loader = new GLTFLoader(); // GLTFLoader.parse 标准签名:parse(数据, 资源根路径, 成功回调, 失败回调) loader.parse( arrayBuffer, "", (gltf) => { observer.next(gltf); observer.complete(); }, (parseErr) => { observer.error(new Error(`GLTF解析失败:${parseErr?.message || parseErr}`)); } ); }) .catch(err => observer.error(err)); }); // tap用于处理不改变流数据的副作用,这里写入缓存后正常透传gltf数据给订阅方 return data$.pipe( tap((gltfMesh) => { this.surfaceMeshes.set(surfaceMeshKey, gltfMesh); }) ); }
关键说明
- 必须使用GLTFLoader做解析:接口返回的是GLTF/GLB格式的二进制结构化数据,包含网格顶点、法线、UV、材质、纹理等多段数据,手动解析需要完全遵循GLTF格式规范,工作量极大,GLTFLoader是Three.js官方提供的标准解析工具,会直接输出可加入场景渲染的Three.js对象实例,没有重复造轮子的必要。
- GLTFLoader除了
parse方法(用于解析已拿到的二进制数据),也可以直接用load方法传入URL发起请求,你当前已经自己封装了fetch请求逻辑,用parse方法匹配现有代码结构即可。 - 代码中新增的前置缓存判断是可选优化,和你原有JSON方法的缓存逻辑匹配,可以避免相同参数重复发起请求,如果不需要可以删掉。
内容的提问来源于stack exchange,提问作者user13856337
相关产品推荐
相关产品推荐

