Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Craziest JavaScript behavior I've ever seen

And that's saying something. This is based on the Google Maps sample for Directions in the Maps API v3.

<html> 
<head> 
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/> 
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
<title>Google Directions</title> 
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> 
<script type="text/javascript"> 
var directionDisplay;
var directionsService = new google.maps.DirectionsService();
var map;


function initialize() {
    directionsDisplay = new google.maps.DirectionsRenderer();

    var myOptions = {
      zoom:7,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    }

    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
    directionsDisplay.setMap(map);
    directionsDisplay.setPanel(document.getElementById("directionsPanel"));
}

function render() {
    var start;

    if(navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function(position) {
          start = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
        }, function() {
          handleNoGeolocation(browserSupportFlag);
        });
      } else {
        // Browser doesn't support Geolocation
        handleNoGeolocation();
    }

    alert("booga booga");


    var end = '<?= $_REQUEST['destination'] ?>';
    var request = {
        origin:start, 
        destination:end,
        travelMode: google.maps.DirectionsTravelMode.DRIVING
    };
    directionsService.route(request, function(response, status) {
      if (status == google.maps.DirectionsStatus.OK) {
        directionsDisplay.setDirections(response);
      }
    });
}

</script> 
</head> 
<body style="margin:0px; padding:0px;" onload="initialize()"> 
<div><div id="map_canvas" style="float:left;width:70%; height:100%"></div> 
<div id="directionsPanel" style="float:right;width:30%;height 100%"></div> 
<script type="text/javascript">render();</script>
</body> 
</html>

See that "alert('booga booga')" in there?

With that in place, this all works fantastic. Comment that out, and var start is undefined when we hit the line to define var request.

I discovered this when I removed the alert I put in there to show me the value of var start, and it quit working. If I DO ask it to alert me the value of var start, it tells me it's undefined, BUT it has a valid (and accurate!) value when we define var request a few lines later.

I'm suspecting it's a timing issue--like an asynchronous something is having time to complete in the background in the moment it takes me to dismiss the alert. Any thoughts on work-arounds?

like image 620
Dan Ray Avatar asked May 11 '10 15:05

Dan Ray


People also ask

What is the hardest topic in JavaScript?

Asynchronous JavaScript (promises, callbacks, async/await) Closures. The event loop. Recursion.

What are the 5 JavaScript statements?

JavaScript statements are composed of: Values, Operators, Expressions, Keywords, and Comments.


2 Answers

What you're assuming is correct navigator.geolocation.getCurrentPosition() is an asynchronous call finished while you're dismissing that alert. To fix this you need to continue your work either from or in the callback function. To do that, rearrange your code to occur when it finishes, like this:

function render() {
    if(navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function(position) {
          var start = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
          var end = '<?= $_REQUEST['destination'] ?>';
          var request = {
              origin:start, 
              destination:end,
              travelMode: google.maps.DirectionsTravelMode.DRIVING
          };
          directionsService.route(request, function(response, status) {
            if (status == google.maps.DirectionsStatus.OK) {
              directionsDisplay.setDirections(response);
            }
          });
        }, function() {
          handleNoGeolocation(browserSupportFlag);
        });
      } else {
        // Browser doesn't support Geolocation
        handleNoGeolocation();
    }
}
like image 73
Nick Craver Avatar answered Oct 25 '22 11:10

Nick Craver


The "asynchronous something" is the call to getCurrentPosition. The alert takes up some time, so that call can complete and invoke the callback that sets the value of "start".

You could try moving the entire wad of code starting from where you define "request" up into the callback on getCurrentPosition. That would delay it until "start" is definitely set to a usable value.

edit yes like Nick shows in his example.

like image 45
Pointy Avatar answered Oct 25 '22 13:10

Pointy