0

I need to access a series of XML documents and am trying to do so with a for loop that generates each request dynamically:

for (i=0;i<routes.length;i++) {
routeRequestURL = "http://webservices.nextbus.com/service/publicXMLFeed?command=routeConfig&a=sf-muni&r=" + routes[i].name + "&terse";
routeRequest.open("GET", routeRequestURL);
routeRequest.send();
routeResponse = routeRequest.responseXML;
route = routeResponse.getElementsByTagName("route")[0];
for (var j = 0; j < route.childNodes.length; j++) {
    if (route.childNodes[j].tagName == "stop") {
        routes[i].stops.push(new Stop(route.childNodes[j].getAttribute("tag"), route.childNodes[j].getAttribute("lat"), route.childNodes[j].getAttribute("lon")));
    }
  }
}

routes is an array of route objects, which have three variables: name, label, and stops, which is itself an array of stop objects.

I tried out the code in Chrome's javascript console, and it worked when I ran each line within the outer loop with routes[0]. When I tried to run the loop in the console, I got the following error message: TypeError: Cannot call method 'getElementsByTagName' of null.

If running each line of code with routes[0] generates no errors, then why is routeResponse null during the first iteration of the for loop? Am I missing a closure error somewhere?

EDIT: I tried to include a readystatechange callback, but, being new to javascript, couldn't quite figure out how to do it. I tried:

for (i=0;i<routes.length;i++) {
routeRequestURL = "http://webservices.nextbus.com/service/publicXMLFeed?command=routeConfig&a=sf-muni&r=" + routes[i].name + "&terse";
routeRequest.open("GET", routeRequestURL);
routeRequest.onreadystatechange = function() {
    routeResponse = routeRequest.responseXML;
    route = routeResponse.getElementsByTagName("route")[0];
    for (var j = 0; j < route.childNodes.length; j++) {
        if (route.childNodes[j].tagName == "stop") {
            routes[i].stops.push(new Stop(route.childNodes[j].getAttribute("tag"), route.childNodes[j].getAttribute("lat"), route.childNodes[j].getAttribute("lon")));
        }
      }
    }
routeRequest.send();
}

It didn't work.

2
  • 3
    You're missing a readystatechange callback, since the request is asynchronous. Commented Oct 3, 2012 at 17:59
  • I'm pretty new to javascript... how would I include that callback? Commented Oct 3, 2012 at 18:19

1 Answer 1

1

Two things:

  1. Inside the readystatechange callback you added, you have to check if the response has finished loading
  2. The callback introduces a closure, which will cause you problems with your reference to i.

The following code should address both issues:

routeRequest.onreadystatechange = (function(i) { return function() {
    if(routeRequest.readyState == 4 && routeRequest.status == 200) {
        routeResponse = routeRequest.responseXML;
        route = routeResponse.getElementsByTagName("route")[0];
        for (var j = 0; j < route.childNodes.length; j++) {
            if (route.childNodes[j].tagName == "stop") {
                routes[i].stops.push(new Stop(route.childNodes[j].getAttribute("tag"), route.childNodes[j].getAttribute("lat"), route.childNodes[j].getAttribute("lon")));
            }
        }
     }
}})(i);
Sign up to request clarification or add additional context in comments.

Comments

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.