three.js循环加载模型bug

在使用Three.js中 使用for循环加载obj模型出现的bug

BUG

直接上代码:


    var objArray = ["1","2","3","4"];
    
    for(var i = 0; i < objArray.length; i++) {
        
        var mtlLoader = new THREE.MTLLoader();
			mtlLoader.setPath("obj/");
			mtlLoader.load("" + objArray[i] + ".mtl", function(materials) {

			materials.preload();

				var objLoader = new THREE.OBJLoader();
					objLoader.setMaterials(materials);
					objLoader.setPath("obj/");
					objLoader.load("" + objArray[i] + ".obj", function(object) {

				    scene.add(object);

					}, onProgress, onError);

				});
         
				}

最新版本的three.js中加载obj模型可以分为两步,第一步先加载mtl文件,提取mtl文件作为对象的材质。第二部加载obj文件,提取obj文件作为
对象的三维网格,然后创建对象。

当我们使用以上方式循环加载一组模型的时候。它会报错。

   
    obj/undefined.obj  NOT_FOUND   X4
   

but i dont't know what happend!

然后在加载obj文件的时候打印出i会发现此事的 i=5 数组越界了所以找不到文件。但是为什么mtl都被加载了呢?

then 我稍微学习了一下发现,由于文件的加载时异步的

第一次加载的时候i=0, mtl加载的时候是正常的,但是加载obj的时候由于是单线程的obj的加载被阻塞了,所以它只好等mtl加载完成将一个函数objLoader.load(i)放到线程池中。
但是由于是异步的,所以在加载第一个mtl加载完成时候循环早已结束。
所以mtlLoader.load(i) (此处i=0)结束的时候,要执行objLoader.load(i)的时候i早已为5,所以会出现NOT_FOUND

解决方案

解决方案1

我发现只要在循环中加入这么一句:

   
    for(var i = 0; i < objArray.length; i++) {
        
        var arr = array[i];
   

这句话在使用ajax的时候很常见,我一直天真的以为它仅仅是用来简化代码的。

解决方案2

可以将需要循环的封装成一个函数,然后外部循环调用。

   
    for(var i = 0; i < objArray.length; i++) {
    
        loadObj(objArray[i]);
         
    }
    
    function loadObj(objName){
        
        //todo
       
    }