Angular+ThreeJS异步渲染问题:sleep/setTimeout无法分步构建场景
解决ThreeJS分步添加物体的异步问题
嘿,我来帮你搞定这个问题!先拆解下你遇到的两个核心坑:
1. 自定义sleep阻塞主线程的原因
JavaScript是单线程语言,你写的同步sleep会把主线程死死占住——浏览器在这段时间里根本没时间更新UI(包括清空场景、渲染新物体),所以所有操作都得等所有sleep跑完才一次性执行,自然看不到分步渲染的效果。
2. setTimeout中this指向错误的问题
当用普通函数做setTimeout回调时,函数内部的this会指向全局对象(浏览器里就是window),而不是你的类实例,所以this.scene就变成undefined了,报错也就理所当然。
正确的实现方案
下面是修复后的完整代码,我们用箭头函数解决this指向问题,同时调整延迟时间让物体按顺序逐个添加:
public buildPalette() { // 先同步清空场景,确保这一步先完成 if (!this.initial) { for (let i = 0; i < this.numOfItems; i++) { this.scene.remove(this.mesh[i + 1]); } // 小提示:如果场景里只有这些mesh,也可以用更简洁的写法:this.scene.clear(); // 注意:scene.clear()会移除所有物体、灯光、相机,有需要保留的元素就别用 this.initial = true; } // 分步添加物体,每个间隔100ms if (this.initial) { for (let i = 0; i < this.numOfItems; i++) { // 箭头函数会继承外层的this,确保能访问到类实例的scene和mesh setTimeout(() => { console.log(`添加第${i+1}个物体`); this.scene.add(this.mesh[i + 1]); }, i * 100); // 关键:每个延迟i*100ms,实现依次添加 } } }
为什么这样能行?
- 箭头函数的this绑定:箭头函数不会创建自己的this,它会直接用外层作用域的this(也就是你的类实例),所以
this.scene和this.mesh都能正常访问。 - 递增的延迟时间:循环里每个setTimeout的延迟是
i*100ms,第一个物体0ms后添加,第二个100ms后,第三个200ms后……这样就完美实现了每隔100ms添加一个的效果。
其他可选的this绑定方法
如果你不想用箭头函数,也可以试试这两种方式:
方法1:提前保存this到变量
public buildPalette() { // ...清空场景的代码... if (this.initial) { const self = this; // 把当前实例的this存到self里 for (let i = 0; i < this.numOfItems; i++) { setTimeout(function() { self.scene.add(self.mesh[i + 1]); // 用self代替this }, i * 100); } } }
方法2:用bind绑定this
public buildPalette() { // ...清空场景的代码... if (this.initial) { for (let i = 0; i < this.numOfItems; i++) { setTimeout(function() { this.scene.add(this.mesh[i + 1]); }.bind(this), i * 100); // 用bind把this绑定到当前类实例 } } }
最后提个小建议:如果你的mesh数组是从索引0开始的,直接用this.mesh[i]就行,不用i+1,代码会更直观哦!
内容的提问来源于stack exchange,提问作者user9209227
相关产品推荐
相关产品推荐

