views:

927

answers:

4
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Maps JavaScript API Example: Simple Streetview Example</title>
<script src="http://maps.google.com/maps?file=api&amp;amp;v=2.x&amp;amp;key=&lt;?=APIKEY?&gt;"
        type="text/javascript"></script>
<script type="text/javascript">

var myPano;
var newPoint;

function initialize() {
  var fenwayPark = new GLatLng(42.345573,-71.098326);
  var address = "1600 Amphitheatre Parkway, Mountain View, CA, USA";

  var geocoder = new GClientGeocoder();
 geocoder.getLatLng(
  address,
  function(point) {
   if (!point) {
    alert(address + " not found");
   } else {
    newPoint = point;
    alert("inside of function: " + newPoint);
   }
  });
 alert("outside of function: " + newPoint);
  panoramaOptions = { latlng:fenwayPark };
  myPano = new GStreetviewPanorama(document.getElementById("pano"), panoramaOptions);
  GEvent.addListener(myPano, "error", handleNoFlash);
}

function handleNoFlash(errorCode) {
  if (errorCode == FLASH_UNAVAILABLE) {
    alert("Error: Flash doesn't appear to be supported by your browser");
    return;
  }
}  
</script>

when I run this code, the alert("outside of function: " + newPoint); have not got any value, but in the function alert("inside of function: " + newPoint); it gets.

complete code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Maps JavaScript API Example: Simple Streetview Example</title>
<script src="http://maps.google.com/maps?file=api&amp;amp;v=2.x&amp;amp;key=ABQIAAAAgVzm2syhpm0A5rAKFMg3FBS-DTtkk0JB-Y_gKL-3MRZwBHch9RSjWJj17-fEEecjCvYeo1i7w_1yPw"
        type="text/javascript"></script>
<script type="text/javascript">

var myPano;

function initialize() {

 var geocoder = new GClientGeocoder();

 var address = "1600 Amphitheatre Parkway, Mountain View, CA, USA";
 geocoder.getLatLng(
  address,
  function(point) {
  if (!point) {
   alert(address + " not found");
  } else {
   panoramaOptions = { latlng:point };
   myPano = new GStreetviewPanorama(document.getElementById("pano"), panoramaOptions);
   GEvent.addListener(myPano, "error", handleNoFlash);
  }
 });
}

function handleNoFlash(errorCode) {
  if (errorCode == FLASH_UNAVAILABLE) {
    alert("Error: Flash doesn't appear to be supported by your browser");
    return;
  }
}  
</script>

I want to show the street view of address:1600 Amphitheatre Parkway, Mountain View, CA, USA when opening the page

+3  A: 

getLatLng() is asynchronous.

You call getLatLng() and some time later it calls your callback with the data. Your "outside of function" code is called immediately after your call to getLatLng(), before the asynchronous call to your "inside of function" callback happens.

RichieHindle
+4  A: 

The inner function is a callback function. Meaning, it waits until the geocode api call has finished running before it executes. This is known as asynchronous execution. You'll notice that the outside alert fires before the inside alert even though the inside alert is written earlier.

Any code that needs a valid newPoint value will need to be executed from within the call back function, just like the inside alert.

Joel Potter
I think I am nitpicking here but to say that 'callback function **waits** while geocode api call has finished running' is not really correct. Actually, when the getLatLang finishes its work, it calls your callback function with results. I am sure you already know this, somehow the description didn't sound right to me.
SolutionYogi
I movemyPano = new GStreetviewPanorama(document.getElementById("pano"), panoramaOptions); GEvent.addListener(myPano, "error", handleNoFlash);to the inside of function, but nothing happened..
skargor
What did you expect to happen? Could you post the complete code?
SolutionYogi
@SolutionYogi I edited it, plz help me slove it.
skargor
@SolutionYogi: I agree. That's why it's called a "callback". However, I wanted to avoid confusing the OP. Perhaps I over did it.
Joel Potter
A: 

Because the callback function where you call the inside alert runs AFTER your outside alert.

Try delaying your outside alert by a second and you'll see that the correct value will be alerted

setTimeout(function(){ alert(newPoint); }, 1000);

This happens because the function where you call the inside alert is asynchronous

EDIT: Please note that the above is bad practice and should only be used to help you understand whats happening and why.

Darko Z
While the timeout may help someone new to async programming understand the concept a little better, they should also be careful to realize that it is not a good technique to use in a code sample like the OP presented. It is not guaranteed that the async call will be finished within 1 second or even 10 seconds (consider very slow connections).
Joel Potter
This is definitely not a good idea. It's impossible to guess how long the async function will take. There is a reason the callback is provided in the first place.
SolutionYogi
Yeah i totally agree with both comments, the timeout was just supposed to help him understand by demonstrating that at the point of calling the outside alert the var was not initialised. That kind of code should never be used for anything but testing purposes...
Darko Z
+1  A: 

You fixed the problem with the asynchronous getLatLng(). The only problem with your new code is that there is no panorama at the address you requested (take the '1600' out and it will work). There is a function that will return the point of the nearest panorama: getNearestPanoramaLatLng(). It will return null if there isn't a nearby panorama. Here's how to use it in your code:

function initialize() {

    var geocoder = new GClientGeocoder();
    var panoClient = new GStreetviewClient();

    var address = "1600 Amphitheatre Parkway, Mountain View, CA, USA";

    geocoder.getLatLng(
    address,
    function(point) {
     if (!point) {
      alert(address + " not found");
     } else {
      panoClient.getNearestPanoramaLatLng(point, function(newPoint) {
       if (newPoint == null) {
        alert("no panorama found");
        return;
       }
       panoramaOptions = { latlng:newPoint};
       myPano = new GStreetviewPanorama(document.getElementById("pano"), panoramaOptions);
       GEvent.addListener(myPano, "error", handleNoFlash);
      });
     }
    });
}
Chris B