I am trying to write a simple function to load an array from XML in javascript. I have successfully been able to send the AJAX result to a function using the success: field when calling $.ajax(...).
Also, I’ve noticed that the return value of the function $.ajax(...) is an Object, which has fields responseText and responseXML (which I would be happy to use). However, even though I can see them in the tree on my console, trying to access them via .responseText does not work (and so prints undefined, the same if I were to try looking up some junk string .this_does_not_exist).
I am going to do this nearly identically with several different XML files, I’d like to do it with code. The reason I’m not content to simply have the success: parameter kick the results to a separate function is because I may use the data multiple times, but only want to load it once. I’m trying to separate loading and using the XML so that it isn’t loaded several times.
Can you tell me why responseText shows up when I output xml_ret, but is not accessible by xml_ret.responseText?
Thanks a lot for your help and patience.
Note: to load test.xml from the same directory, you need to launch Chrome or Chromium this way:
chromium-browser --allow-file-access-from-files
test.html:
<html>
<head>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
function print_XML(xml)
{
console.log( "in printXML" );
console.log(xml);
$(xml).find("point").each(function()
{
var loaded_row = [ parseInt($(this).attr("number_protein_groups")), parseInt( $(this).attr("log_likelihood") ) ];
console.log( loaded_row );
});
}
function load_and_print_XML(fname)
{
console.log( "in load_and_print_XML" );
xml_ret = $.ajax({
type: "GET",
url: fname,
dataType: "xml",
success: print_XML
});
console.log( "xml_ret" );
console.log( xml_ret );
console.log( xml_ret.responseText );
}
</script>
</head>
<body>
<script type="text/javascript">
xml_data = load_and_print_XML("test.xml");
/* do something with xml_data here */
</script>
</body>
</html>
test.xml
<?xml version="1.0" encoding="utf-8" ?>
<results>
<replicate_result graph_filename="yeast_1.pivdo">
<point number_protein_groups="10" log_likelihood="20"/>
<point number_protein_groups="20" log_likelihood="40"/>
<point number_protein_groups="40" log_likelihood="60"/>
<point number_protein_groups="50" log_likelihood="50"/>
<point number_protein_groups="60" log_likelihood="55"/>
</replicate_result>
</results>
My console:
in load_and_print_XML
test.html:30xml_ret
test.html:31
Object
abort: function (a){a=a||"abort",p&&p.abort(a),w(0,a);return this}
always: function (){i.done.apply(i,arguments).fail.apply(i,arguments);return this}
complete: function (){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this}
done: function (){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this}
error: function (){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this}
fail: function (){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this}
getAllResponseHeaders: function (){return s===2?n:null}
getResponseHeader: function (a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c}
isRejected: function (){return!!i}
isResolved: function (){return!!i}
overrideMimeType: function (a){s||(d.mimeType=a);return this}
pipe: function (a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()}
progress: function (){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this}
promise: function (a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}
readyState: 4
responseText: "<?xml version="1.0" encoding="utf-8" ?>↵<results>↵ <replicate_result graph_filename="yeast_1.pivdo">↵ <point number_protein_groups="10" log_likelihood="20"/>↵ <point number_protein_groups="20" log_likelihood="40"/>↵ <point number_protein_groups="40" log_likelihood="60"/>↵ <point number_protein_groups="50" log_likelihood="50"/>↵ <point number_protein_groups="60" log_likelihood="55"/>↵ </replicate_result>↵</results>"
responseXML: Document
setRequestHeader: function (a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this}
state: function (){return e}
status: 200
statusCode: function (a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this}
statusText: "success"
success: function (){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this}
then: function (a,b,c){i.done(a).fail(b).progress(c);return this}
__proto__: Object
test.html:32undefined
test.html:9in printXML
test.html:10
Document
<results>
<replicate_result graph_filename="yeast_1.pivdo">…</replicate_result>
</results>
test.html:15[10, 20]
test.html:15[20, 40]
test.html:15[40, 60]
test.html:15[50, 50]
test.html:15[60, 55]
To the question:
It’s happening because when you do console.log of an object, for example in chrome, that keeps the reference to the object in the console. If the object changes, those changes are reflected by chrome’s console.
So what’s happening is that when you do:
the ajax request haven’t finished and the responseText still haven’t been assigned, that’s why it appears as undefined. However the xml_ret object printed is a reference to an object so when the ajax request finishes if you go to check the values on the console it has a “responseText” property because it has already been set.
You can see that if you debug the code and add a breakpoint in this line:
When looking at the file xml_ret it doesn’t have the “responseText” property.
PS: I’ll need to review this comment for sure. Too late too think 😛