2016-09-23 49 views
0

我试图做的是:负荷大量的模型For循环

  1. 从服务器获取一个JSON文件,其中包含有关我的模型数据
  2. 使用帘布装载机里面一个for循环将它们添加到现场
  3. 它们添加到一个数组

这里是我的功能:

function getJSON(callback) { 
    var temp = $.getJSON("data/data.json", function(data) { 
     //execute the callback, passing it the data 
     callback(data); 
    }); 
} 

function loadModels() { 

    //get our JSON 
    getJSON(function(data) { 

     //evaluate data 

     nodes = data.library[0].model.nodes; 

     nodesLen = nodes.length; 

     //Load nodes and add them to scene and array 
     for (var i = 0; i < nodesLen; i++) { 

      var url = nodes[i].url; 

      // PLY loader 
      var loader = new THREE.PLYLoader(); 
      loader.load(url, function(geometry) { 

       geometry.computeFaceNormals(); 

       var material = new THREE.MeshPhongMaterial({ color: 0xffffff, vertexColors: THREE.VertexColors, transparent: true, side: THREE.DoubleSide }); 
       var mesh = new THREE.Mesh(geometry, material); 

       mesh.stepNum = i; 

       console.log(i); 

       mesh.position.x = 0; 
       mesh.position.y = 0; 
       mesh.position.z = 0; 

       //Add to scene 
       scene.add(mesh); 

       //Push into array 
       nodesArr.push(mesh); 

      }); 
     } 

    }); 

} 

问题:它们加载不正确。当我在PLY加载器中检查“console.log(i)”的输出时,它总是返回相同的值。我认为,在加载模型时,另一个循环已经开始。如何指示循环等到所有函数在另一个循环开始之前完成?

+0

这可能帮助你:HTTP:// stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example - 它不是那么明显,但JavaScript引擎做的事情略有不同,比你想象的。 –

回答

1

正如评论已经提到的,这应该解释bahviour相当不错:JavaScript closure inside loops – simple practical example

的问题基本上是这样的:功能loader.load()是异步的,这意味着该函数调用会立即返回,不会等待来自网络的响应。因此,您的循环将立即完成(此时i等于nodesLen并且所有HTTP请求都已启动)。但是当时没有任何要求完成。这只会在很长一段时间后发生(说到几微秒与几百毫秒),此时您的回调(function(geometry) {})第一次被调用。

对此的一个解决方案在上面链接的答案中进行了解释:您可以使用闭包来将我的当前值“封存”到回调中。这可能会解决你的问题,但是你仍然有很多并发请求正在进行(也不是一件坏事,浏览器可以处理它)。

但是,为了回答你的主要问题:如果你想下一个请求要等到前一个请求完成,你需要做的是这样的:

var remainingUrls = [ /* ... list of all model-urls ... */ ]; 

function loadNext() { 
    // get the first of the remaining urls and remove it from the array 
    var nextUrl = remainingUrls.shift(); 

    if (!nextUrl) { 
    // when there is no next url, we are done here 
    return; 
    } 

    loader.load(nextUrl, function(geometry) { 
    addToScene(geometry); 

    // now it's time to start loading the next file 
    loadNext(); 
    }); 
} 

// start loading the whole list 
loadNext(); 
+0

伟大的解决方案!这是如何开箱即用的真实例子。非常有帮助,非常感谢:) – leota