12

After hours of search, I Have a problem with my code Below. In fact, I'm not very far from answer I think but I'm still blocked…

I have an anonymous function called inside a loop and I want to access and refresh global variables but I tried with window.myvariable, with another function and nothing happen…

this my code :

for (var i = 0; i < SHP_files.length; i++) {
            shapefile = new Shapefile({
                shp: "shp/polygon/"+SHP_files[i]+".shp",
                dbf: "shp/polygon/"+SHP_files[i]+".dbf",
                }, function(data) {

                    polygon_layer.addLayer(new L.GeoJSON(data.geojson,{onEachFeature: onEachFeature, style: polygonStyle}));
                    polygon_layer.addTo(map);
                    console.log(polygon_layer.getLayers()); // IS OK
                });
        };
        console.log(polygon_layer.getLayers()); // IS EMPTY !!

So, How i could transform this anonymous function in order to have something that I can access from my code who's following that ?

Thanks a lot, and sorry for my english not very good…

5
  • Do some research on asynchronous (non-blocking) coding patterns. Commented Oct 3, 2013 at 20:18
  • I don't quite understand your question, what I'm seeing here is you passed a function as argument. Are you sure it's called in the constructor? Commented Oct 3, 2013 at 20:24
  • What does new Shapefile() do? If it loads the .shp and the .dbf files over AJAX, and the function is a success callback, the loading can happen asynchronously. ("in the background"). That means that after the loop ends, the files will only have begun to load, they'll be added to polygon_layer later. Commented Oct 3, 2013 at 20:43
  • 1
    @user2736012 That's pretty much a nonexplanation. Commented Oct 3, 2013 at 20:44
  • @millimoose: What is? I didn't attempt an explanation, but rather told the research topics to pursue. Is suggesting personal research verboten here? Commented Oct 3, 2013 at 21:48

2 Answers 2

5

This is your typical problem with asynchronous code execution. You example code does NOT execute from top to bottom. In particular, your anonymous function does NOT get executed until Shapefile is done with whatever it is doing. In the meantime, your JS gets executed in order. Therefore, the last line of your above code, will probably execute before the anonymous function ever will.

To fix this, you will need to trigger any code that depends on the Shapefile response from within its callback:

for (var i = 0; i < SHP_files.length; i++) {
    shapefile = new Shapefile({
        shp: "shp/polygon/"+SHP_files[i]+".shp",
        dbf: "shp/polygon/"+SHP_files[i]+".dbf",
        }, function(data) {
            polygon_layer.addLayer(new L.GeoJSON(data.geojson,{onEachFeature: onEachFeature, style: polygonStyle}));
            polygon_layer.addTo(map);
            executeMoreCode();
        });
};

function executeMoreCode() {
    console.log(polygon_layer.getLayers()); // IS OK
}
Sign up to request clarification or add additional context in comments.

7 Comments

"...will probably execute before the anonymous function..." should read "...will definitely execute...". Since the environment is single-threaded, any asynchronous code (like the callbacks) will need to wait for the thread to be available, which means the console.log() at the bottom will always execute first.
Well, I see your point, but I purposely said probably because it is true. Since the asynchronous call happens in a loop, I don't know how many execution cycles it takes up. If we are talking about 100 or 200 iterations, there is a good chance that the first asynchronous call comes back before the loop gets exited. So at that point, the polygon_layer array may no longer be empty. But you are right in that it definitely will not have ALL the data yet.
Actually, no. Because the loop itself (followed by the call to console.log()) is synchronous, it will block any asynchronous activity until it's complete. So take an exaggerated situation where the for loop takes 1 second to complete. If the first callback is ready after only 100 milliseconds, it still won't be invoked because the for loop (and then the console.log()) will block it. Async code always needs to wait for any currently running sync code to finish.
Ok, thank you I understand the problem and why it was blocked. But I still have an interrogation because, I added a console.log("i",i); inside my success callback and after refresh, my console display i=2 twice… like if the first passage was not complete… And my polygon_layer is also populated with the second shapefile twice… In fact, I would loop from all the .shp and .dbf files of my folder, do some stuff and at the end of that do some final code… is it possible with 1 to n asynchronous ajax request ?
@ViotCamille: Your particular issue comes from non-blocking aspect of the code. Your callbacks will always happen after the loop and the last console.log() have finished. So ask yourself, what is the value of i after the loop is done? It'll be the last value that i was incremented to. But the issue in the code in the question isn't related to that. Your issue there is that you want the console.log() to run after all the callbacks are done. The answers given here don't really help with that.
|
2

Try defining your variables, in this case polygon_layer, outside of the for loop or the function. See the following example:

var f;
for(var i=0; i<5;i++){
    (function(){
        f = 10;
        console.log(f); // Outputs 10
    })();
}
console.log(f); // Also outputs 10

2 Comments

I highly doubt this is the cause of the problem. He/she probably already has polygon_layer defined outside the loop (and if not, it would just be a global variable anyway). The issue is more than likely the asynchronous nature of the Shapefile call.
Likely true, was simply trying to address easiest solution first.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.