Question

I'm trying to write a script to retrieve a WOEID and interface with the Yahoo Weather API. I'm constructing a URL based on latitude and longitude values from stuff in a database I'm using, and can do this perfectly fine.

However, when it comes to storing that URL as a string that I can use in other functions, I'm having trouble. After some initial reading it seems to be a problem to do with onreadystatechange and scope, but I can't seem to get my head around it to be able to store my variable.

Here is my code so far:

 //<![CDATA[

var latitude = "";
var longitude = "";
var yahooAppID = "";
var yql = "";

//example yahoo request
//http://where.yahooapis.com/geocode?q=38.898717,+-77.035974&gflags=R&appid=SKUTk24k


function getLatLng() {
    var routeID = 5;
    var get = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
    get.open('POST','process.php', true)
    get.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    get.send('command=fetch&rid='+routeID);
    get.onreadystatechange = function(){
        if(get.readyState==4 && get.status == 200) {
                os = eval('(' + get.responseText + ')');
                latitude = os.start.lat;
                longitude = os.start.lng;
                //var yql = 'select * from flickr.places where lat='+latitude+' and lon='+longitude;
                yql = "select * from flickr.places where lat=" +latitude+ " and lon="+longitude;
            }
            document.write(yql);
        }
        document.write(yql);
    }


function test() {
    getLatLng();
}
//]]>

The first document.write(yql); seems to produce the correct string, but the second does not, so I know that the value has not stuck.

Thanks in advance if anyone can help.

Was it helpful?

Solution

You're not looking at a scoping issue — rather, a timing issue. AJAX requests (at least the way you've configured it) happen asynchronously, so the rest of your script will execute while the AJAX request is loading. So yql won't be updated until the very end.

Also, warning: by the time the request completes, you can no longer use document.write. Use alert() or DOM manipulation.

Life cycle looks like this:

  1. Script is executed normally
  2. Anonymous function is bound to onreadystatechange
  3. readyState changes from "unsent" to "headers received" to "loading" to "done". Your function gets called every time, but you only set yql when the ready state is "done."
  4. readyState is done, and you generate yql.

So, just call your processing function from inside the if:

if(get.readyState==4 && get.status == 200) {
        os = get.responseXML;
        //find lat + lng
        yql = "select * from flickr.places where lat=" +latitude+ " and lon="+longitude;
        process(yql); //here!
}



function process(yql) {
   alert(yql);     //do something more useful eventually
}

jsFiddle

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top