在For循环

时间:2016-09-23 10:51:15

标签: javascript for-loop three.js

我想做的是:

  1. 从服务器获取JSON文件,其中包含有关我的模型的数据
  2. 在for循环中使用PLY加载程序将它们添加到场景中
  3. 将它们添加到数组
  4. 以下是我的功能:

    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);
    
                });
            }
    
        });
    
    }
    

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

1 个答案:

答案 0 :(得分:1)

正如评论中已经提到的,这应该很好地解释了bahviour:JavaScript closure inside loops – simple practical example

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

我在上面的链接中解释了一个解决方案:你可以使用一个闭包来密封&#34; i的当前值进入回调。这可能会解决您的问题,但您仍然会有很多并发请求(也不一定是坏事,浏览器可以处理它)。

但回答你的主要问题:如果你想等待下一个请求,直到完成上一个请求,你需要做这样的事情:

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();