0

I have the following JS:

Meteor.startup(function () {
  map = L.map('map_canvas').locate({setView: true, maxZoom: 21});
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
      attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
  }).addTo(map);
    bounds = {};    
    map.on('locationfound', function(e){ 
      bounds.bottomLeftLat = map.getBounds()._southWest.lat;
      bounds.bottomLeftLng = map.getBounds()._southWest.lng;
      bounds.topRightLat = map.getBounds()._northEast.lat;
      bounds.topRightLng = map.getBounds()._northEast.lng;
      console.log(bounds);
    });
  console.log('outside function: '+bounds);
});

My first console.log outputs correctly the 4 object properties with their values in the console, but the outside function log outputs an empty object, and when I try to access bounds outside of Meteor.startup then it's not even defined. I understand that functions limit the scope of variables but if bounds is defined outside the anonymous function, without 'var', isn't it considered to be a global?

  1. Why can I access 'map' but not 'bounds' outside of Meteor.startup?
  2. How could I rewrite this code by following more smart patterns (module?) so that I can both make bounds available in other parts of the script and successfully add the four properties as I am attempting?

edit the event is fired - after manually firing it, I still get an empty object:

map.fire("locationfound");
Object {type: "locationfound", target: e, bottomLeftLat: 50.05008477838258, bottomLeftLng: 0.384521484375, topRightLat: 51.63847621195153…}
 MainClient.js:12
e {options: Object, _container: div#map_canvas.leaflet-container leaflet-fade-anim, _panes: Object, _mapPane: div.leaflet-map-pane, _tilePane: div.leaflet-tile-pane…}
bounds
Object {}

2 Answers 2

2

It is seeing bounds but your console.log happens before the callback on the locationfound event, so its still empty when you're trying to access it.

All of your initialization will happen the first time a locationfound event fires, and a log at that point will show the results you expect.

A few thoughts.

  1. In general declaring variables without var is frowned upon. If you want to access it globally, declare it with var in a global context, or (ideally) use a namespace variable and declare all your global variables as properties of that.

  2. If you want to access bounds after it has been modified, you can put the call to the functions you want to run inside the callback

Update to clarify your code's behavior

Here is how your code executes.

//This is the startup function for meteor.  It is passed a function, 
//and executes that function when the code starts up
Meteor.startup(function () {
    //You're now inside the function you passed to startup, and you initialize map
    //...
    bounds = {};    
    //here you call the `on` function on map, and bind a 
    //callback function to the locationfound event
    map.on('locationfound', function(e){ 
      //This code is inside the callback and will be executed when the event occurs 
      
      // code initializing bounds

      console.log(bounds); //this will show the full definition of bounds
      //callback ends here
    });
  //this is outside the callback but still inside startup, 
  //and occurs immediately after the call to map.on
  console.log('outside function: '+bounds); //bounds is still empty
}); //end the startup function

It seems like the key thing you need to understand is the on function. It is a leaflet function that takes 2 arguments, an event type and a callback function, and binds the callback function to the event. The callback function then runs when the event occurs, not before. The callback does not run immediately. Instead the code continues executing, and will execute the callback code when the event occurs.

Documentation for on

Sign up to request clarification or add additional context in comments.

10 Comments

I think I'll rephrase my question because I don't understand anything:) So, even if the console.log 'outside function' is written after the event, it's executed first?
Thanks, so if it is a timing issue, then why when I type bounds in my Web Developer console I still get an empty object?
probably because the event hasn't occurred. I don't know what the locationfound event is, but if its never triggered the code will never be run.
You could try manually triggering it with map.trigger("locationfound") in the console. api.jquery.com/trigger
map is not a jquery object so it doesn't have the trigger method.. (it's a LeafLet object) but the timing reasoning doesn't make sense, the event is executed as I'm getting the console.log from inside the callback.. so bounds.bottomLeftLat etc should be there..
|
1

This is what called javascript event loop The code outside the 'map' can access to the bounds var but you try to access it immediately after you defince the locationfound event of the map - the bounds only initialise when this event will occure - so what are you getting in the console is just an empty object that you defined before "bounds = "{}"

What you did is correct - you can access the bounds only inside the locationfound event cause only then you initialize it

2 Comments

Sorry I don't understand your answer.. could you rephrase a bit?
Yes. you can't get the actual bounds outside the callback event(meaning map.on('locationfound', function(e){})); because only after this even(locationfound) is firing, you set the bounds variant with the map.getBounds() function cause only then you get them. i made you a code example

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.