2016-09-23 93 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