PDA

View Full Version : Help with a loop


Hysteria862
04-14-2008, 10:21 PM
Hi, I'm trying to implement a method where a user enters the name of a music artist, and the request that retrieves data containing a list of song tracks by that artist, and then prints the tags associated with these tracks (all of these using methods in the Audioscrobbler API).

This should be quite simple I'd imagine, my code adds all the correct information (artist, title, tags etc), but only adds the last item in the for loop. How can I get it to add them all?

Thanks


function addtopTracks(event)
{
var artist = document.getElementById("lfmsearch");
var a = TutTB_TrimString(artist.value);
var http = new XMLHttpRequest(); //new request



http.open("GET", "http://ws.audioscrobbler.com/1.0/artist/"+a+"/toptracks.xml", true);//get list of tracks by the artist

http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {


var track = http.responseXML.getElementsByTagName("track");
var name = http.responseXML.getElementsByTagName("name");
var url = http.responseXML.getElementsByTagName("url");
//for loop to find all tracks by the artist
for (var i = 0; i < track.length; i++) {

var p = name[i].firstChild.nodeValue;//get name of each track
var q = url[i].firstChild.nodeValue;
var title = a + " - " + p;

var http4 = new XMLHttpRequest(); //new request
http4.open("GET", "http://ws.audioscrobbler.com/1.0/track/"+a+"/"+p+"/toptags.xml", true);//get tags associated with each track
http4.onreadystatechange = function() {//Call a function when the state changes.
if(http4.readyState == 4 && http4.status == 200) {

var str = "";
//get first 5 tag elements returned
var ts = http4.responseXML.getElementsByTagName("name")[0].firstChild.nodeValue;
var ts2 = http4.responseXML.getElementsByTagName("name")[1].firstChild.nodeValue;
var ts3 = http4.responseXML.getElementsByTagName("name")[2].firstChild.nodeValue;
var ts4 = http4.responseXML.getElementsByTagName("name")[3].firstChild.nodeValue;
var ts5 = http4.responseXML.getElementsByTagName("name")[4].firstChild.nodeValue;
var f = str + " " + ts + " " + ts2 + " " + ts3+ " " + ts4+ " " + ts5;








var http2 = new XMLHttpRequest(); //new request
var data = "object="+q+"&title="+title+"&tag="+f;// information to be sent, a uri, title and tags of the track


http2.open("POST", "http://dipper.csd.abdn.ac.uk/Taggr/api/Tags", true);//post request to server
http2.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http2.setRequestHeader("Content-length", data.length);
http2.setRequestHeader("Connection", "close");
http2.onreadystatechange = function() {//Call a function when the state changes.
if(http2.readyState == 4 && http2.status == 200) {

var x=http2.responseXML.getElementsByTagName("submission")[0].firstChild.nodeValue;//get response from server
alert(x);

}


}
http2.overrideMimeType('text/xml');

http2.send(data);// send request

}
}

http4.overrideMimeType('text/xml');

http4.send(null);// send request


}



}


}

http.overrideMimeType('text/xml');

http.send(null);// send request




}

A1ien51
04-15-2008, 02:09 AM
You are using a for loop with a global variable so it overwrites itself in the loop.

Your best bet would be to find a way to send all of the data up to the server at once and return it. It is easier on the system than sending up a bunch of requests.

If you do not want to do that, you need to find a way to either not use a global variable [use a library such as JQuery or Prototype.js to make the Ajax call] or make your loop not use a for. Instead when the response comes back, fire off the next one.

Eric

Hysteria862
04-15-2008, 03:36 PM
Thanks for the reply, I've taken it out of the for loop and I've figured it might be easier to get the values from another method, now I know this method works, I've tested the 'str' variable using an alert and the correct tags are returned for each track, the problem is I can't seem to reference it by using return, I just get 'undefined'. Does anyone know how I can reference the variable so I can use it in this method?

It does work, I just can't reference it correctly. I've highlighted where I'm accessing the other method. Thanks


function addtopTracks(event)
{

var artist = document.getElementById("lfmsearch");
var a = TutTB_TrimString(artist.value);
var http = new XMLHttpRequest(); //new request



http.open("GET", "http://ws.audioscrobbler.com/1.0/artist/"+a+"/toptracks.xml", true);//get list of tracks by the artist

http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {

var track = http.responseXML.getElementsByTagName("track");
var name = http.responseXML.getElementsByTagName("name");
var url = http.responseXML.getElementsByTagName("url");
//for loop to find all tracks by the artist
for (var i = 0; i < track.length; i++) {

var p = name[i].firstChild.nodeValue;//get name of each track
var q = url[i].firstChild.nodeValue;
var title = a + " - " + p;
var returntags = tracktags(a,p);


var http2 = new XMLHttpRequest(); //new request
var data = "object="+q+"&title="+title+"&tag="+returntags;// information to be sent, a uri, title and tags of the track


http2.open("POST", "http://dipper.csd.abdn.ac.uk/Taggr/api/Tags", true);//post request to server
http2.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http2.setRequestHeader("Content-length", data.length);
http2.setRequestHeader("Connection", "close");
http2.onreadystatechange = function() {//Call a function when the state changes.
if(http2.readyState == 4 && http2.status == 200) {

var x=http2.responseXML.getElementsByTagName("submission")[0].firstChild.nodeValue;//get response from server
alert(x);

}


}
http2.overrideMimeType('text/xml');

http2.send(data);// send request




}



}


}

http.overrideMimeType('text/xml');

http.send(null);// send request




}




Method works, just can't seem to access str from the other method.

function tracktags(string, string2)
{

var str = "";
var http = new XMLHttpRequest(); //new request

http.open("GET", "http://ws.audioscrobbler.com/1.0/track/"+string+"/"+string2+"/toptags.xml", true);//post request

http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {


var p= http.responseXML.getElementsByTagName("name")[0].firstChild.nodeValue;
var p2= http.responseXML.getElementsByTagName("name")[1].firstChild.nodeValue;
var p3= http.responseXML.getElementsByTagName("name")[2].firstChild.nodeValue;
var p4= http.responseXML.getElementsByTagName("name")[3].firstChild.nodeValue;
var p5= http.responseXML.getElementsByTagName("name")[4].firstChild.nodeValue;


var f = str + " " + p + " " + p2 + " " + p3 + " " + p4 + " " + p5;
str = f;


return str

}

}




http.overrideMimeType('text/xml');

http.send(null);// send request



}

Spudhead
04-15-2008, 04:24 PM
You've got the return call inside the IF statement, so your function will only return something if:

(http.readyState == 4 && http.status == 200)

Which doesn't allow for the server returning an error message, or nothing at all, which it looks like is probably happening.

Hysteria862
04-15-2008, 06:54 PM
Thanks, I'm not sure its a server problem though, I tried an alert(str) instead of return str to test this and I got the data back fine, problem seems to be retrieving it from another method, as all I am returned with is 'undefined' instead of each value of str.