0

I have been experimenting with babylonjs and so far everything is great. I am able to load meshes and animate them just fine when everything is in the ImportMesh callback function within the same file. However; when I try to split things up and do something simple like below, I seem to get these race conditions. Take this example:

var models = ["brick_wall", "tree1", "person1"]

for (var i =0;i<models.length;++i) {


    BABYLON.SceneLoader.ImportMesh(models[i], "models/","tree.babylon", scene, (newMeshes) => {


        this.meshMap[models[i]] = newMeshes[0]
        console.log("mesh set:" + models[i])
    });
}

The console log gets printed out as "mesh set: undefined". I'm assuming because import mesh executes the callback function in its own thread before "i" has even had a chance to be set? However I'm having trouble getting my head around as to how "i" and/or models list would still not be set when simply doing a console print within the callback. When I do a console print of:

models[1] 

within the same callback, I am able to see the value correctly? Makes no sense :(

Does anyone know whats going on here with import mesh in regards to threading? Is there a best practices for babylonjs with waiting for threads? I tried using the scene.executewhenready but I still cannot seem to store and retrieve anything in a variable outside the callback.

efel
  • 1,054
  • 3
  • 14
  • 29

1 Answers1

2

I'm assuming because import mesh executes the callback function in its own thread before "i" has even had a chance to be set

No. Note that JavaScript is (mostly...and definitely in this case) single threaded.

When I do a console print of: models[1] within the same callback

This is because the variable i will point to the last value that was assigned (models.length) in this case.

Note: JavaScript closures capture variable not value. So you need to make a new variable in each loop iteration.

Fixed code

var models = ["brick_wall", "tree1", "person1"]

for (var i =0;i<models.length;++i) {

(function(index){
    var i = index;
    BABYLON.SceneLoader.ImportMesh(models[i], "models/","tree.babylon", scene, (newMeshes) => {


        this.meshMap[models[i]] = newMeshes[0]
        console.log("mesh set:" + models[i])
    });
})(i);

}

Here is a video demonstrating this principle : https://www.youtube.com/watch?v=hU4cbxpe49Y

basarat
  • 261,912
  • 58
  • 460
  • 511
  • Thank you. This works. So if I understand correctly this is because the "i" variable is not separate during the for loop scope. It is more of like a reference that gets updated with each count? Since javascript is function scope and not bracket scope, this is why adding a funciton works? I do appreciate the solution but is there a "cleaner" way of doing this? – efel Sep 21 '15 at 10:55
  • figured out a cleaner way to do this using models.forEach syntax – efel Sep 21 '15 at 15:43