Three.js GLTF加载场景下Promise.all未等待所有任务完成提前触发
问题核心原因
processTransformModel函数未将内部创建的Promise链返回到外部,调用时返回值为undefined,导致push到promises数组的并非可跟踪的Promise实例- 返回的Promise链未等待GLTF资源实际加载完成,只要走到发起加载请求的步骤就会被提前标记为resolved
- 内层Promise的
.then回调中调用gltfLoader.load时,没有将该异步加载操作的结果返回到Promise链中,回调执行完就会直接触发外层Promise的resolve,完全不等GLTF加载结束 - 非zip分支存在笔误:
resolve(url)中的url未定义,实际应为resolve(model.url) gltfLoader.load本身是异步方法,其加载完成、加载失败的逻辑没有被纳入Promise跟踪范围,导致Promise.all判定所有任务完成时,实际仍有大体积模型在加载过程中
- 内层Promise的
修复方案
首先调整processTransformModel函数,完整返回带有错误捕获的Promise链,确保每一步异步操作都被正确跟踪:
function processTransformModel(model) { // 第一步:解析得到实际的gltf/glb文件路径 return new Promise((resolve, reject) => { if (model.url.match(/\.zip$/)) { new THREE.ZipLoader().load(model.url) .then(zip => { manager.setURLModifier(zip.urlResolver); const gltfPath = zip.find(/\.(gltf|glb)$/i)[0]; resolve(gltfPath); }) // 将zip加载的错误传递到外层Promise,避免未捕获错误 .catch(reject); } else { // 修复原笔误,使用入参model的url resolve(model.url); } }) // 第二步:返回gltf加载的Promise,让链等待加载完成 .then(file => { // 使用GLTFLoader内置的loadAsync方法,直接返回Promise,自动跟踪加载状态、捕获错误 return gltfLoader.loadAsync(file); }) .then(gltf => { // 在此处执行对gltf对象的原有操作 return gltf; }); }
其次调整原有Promise.all的回调逻辑:
- 修复Promise链后,
Promise.all的then回调触发时已经代表所有GLTF模型加载完成,可直接在回调中执行loadAttachModels(),无需再通过manager.onLoad绑定回调,避免绑定时机晚于LoadingManager触发onLoad的问题:
Promise.all(promises) .then(() => { loadAttachModels(); }) .catch(e => { // 原有错误处理逻辑 });
注:如果必须依赖LoadingManager的onLoad回调,需要在所有加载发起前完成
manager.onLoad的绑定,避免绑定时机过晚导致回调不触发。
内容的提问来源于stack exchange,提问作者Minichua
相关产品推荐
相关产品推荐

