Javascript XmlHttpRequest callback - javascript

Trying to get my head around http requests and asynchronous javascript behaviour.
function httpGetAsync(url, callback){
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
console.log(xmlHttp.responseText); // prints the ip address
callback(xmlHttp.responseText);
}
}
xmlHttp.open("GET", url, true)
xmlHttp.send(null);
}
httpGetAsync("http://httpbin.org/ip", function(){
console.log(this); // doesn't print the ip address
})
The http request is just a simple one that returns a json formatted ip address of the get request. In the function definition the ip address can be printed to the console just fine however in the callback the console prints out the window object. this is probably the wrong thing to use, how do I access the data in xmlHttp.responseText in the callback?

callback(xmlHttp.responseText);
You are calling a function. You are passing it an argument.
function(){
console.log(this); // doesn't print the ip address
}
Your function is not expecting to receive any arguments. Change that, then use that argument.
function(my_argument){
console.log(my_argument);
}
See also How does the “this” keyword work?

You're calling callback(xmlHttp.responseText), so...
httpGetAsync("...", function(response) {
console.log(response);
});
Simple!
One small point: I would recommend putting the .open call before the onreadystatechange, because in some (older) browsers calling .open will reset event handlers.

Related

XMLHttpRequest does not seem to do anything

i have been trying very unsuccessfully to download a binary file from my server using jquery-ajax, which i finally gave up. so now i am trying to use XMLHttpRequest instead. however, i cannot even get a simple example working.
strangely enough, this code does not appear to do anything. i copy/pasted this from w3schools and this example is near identical to many other examples. it does not work for me in either chrome or FF:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
// Action to be performed when the document is read;
}
};
xhttp.open("GET", '/blah/blah/output.png', true);
xhttp.send();
we go into the onreadystatechange function only once, on the open() statement with an xhttp.readyState equal to one, but not on the send() step. i should think it would at least throw some kind of error rather than do nothing at all.
also, as an experiment, i purposely fed the open() a bad url - but again no reply.
can anybody tell me what i might be doing wrong?
thank you very much.
Your code looks correct to me, which points to some external cause.
Is your code flowing all the way through to the end of the execution context? Browsers will hold onto network requests until the engine yields back to the browser.
For instance:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
// Action to be performed when the document is read;
}
};
xhttp.open("GET", '/blah/blah/output.png', true);
xhttp.send();
while(true){}
will never send the call.

Using this keyword in XMLHttpRequest callback

What is difference between using this keyword vs variable name in XMLHttpRequest callback?
var req = new XMLHttpRequest();
req.open("GET", encodeURI(uri), true);
req.onreadystatechange = function () {
if (this.readyState == 4) {
req.onreadystatechange = null; //avoid memory leaks
if (this.status == 200) {
var res = JSON.parse(req.responseText).d;
console.log(res);
}
}
};
req.send();
Can I just use req instead of this, like if (req.readyState == 4)?
There is no difference in onreadystatechange handler by default this refers to the XMLHttpRequest object itself.
So yes, you can use either this or req
I myself have encountered this similar problem recently, but I extended it to more general case: which context does this resolved to in callback?
regard to 3 prevalent callback type: setTimeout, XMLHttpRequest, DOM
I read from the doc for first type, setTimeout, this will resolved to window object
for XMLHttpRequest situation, this will resolved to XMLHttpRequest object itself, https://stackoverflow.com/a/6542261/4730119 this link will give you a explain and here is my test, for which I GET requested api.json's content is a plain simple object and successfully printed in console, notice I used this.responseText, not like most book taught using XHR object request.responseText
and last for DOM, it's just like XHR, this will resolved to object for which the callback added
document.querySelector('input')
.addEventListener('input', function(e){console.log(this)});
// will print input object

Function delivers value, before ajax request changed it

I am running an ajax request to retrieve a value of either 0,1, or 2 based upon some mysql code in the "check_answer_status.php" file. For test purposes, I have included the alert to check whether the general ajax and mysql request works fine and it does, hence the value contained within "Questiions.answerStatus" at the time of the alert is correct. However, my problem is that the function "checkAnswerStatus" has already executed and did not change the inital value of "answerStatus" (which I set to 50 for test purposes).
Context: sometime later in the code I want to execute code dependent on the value of the variable "answerStatus".
I believe I need to somehow include something like an "oncomplete" or something comparable, but I do not know how to do that. Can anyone help me out? Many thanks!
var = Questions = {
answerStatus:50,
checkAnswerStatus : function(question){
var xmlhttp;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
test = xmlhttp.responseText;
Questions.answerStatus = test;
alert(Questions.answerStatus);
}
}
xmlhttp.open("POST","../../include/check_answer_status.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("q="+question);
},
The request you make is asynchronus (the third parameter of the xmlhttp.open function). If you changed it to:
xmlhttp.open("POST","../../include/check_answer_status.php",false);
it should work.
Another options is to pass a callback to your checkAnswerStatus function, and call the callback when the request finishes. Example:
checkAnswerStatus : function(question, callback){
var xmlhttp;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
test = xmlhttp.responseText;
Questions.answerStatus = test;
callback(Questions.answerStatus); //call the function
}
}
xmlhttp.open("POST","../../include/check_answer_status.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("q="+question);
}
and then you will call the function like this:
Questions.checkAnswerStatus("bla bla", function(answerStatus) {
alert(answerStatus);
});
in addition to Nemos answer I would recommend you read following resources from MDN:
More technical API documentation for a brief overview of all the possibilities:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
More real life usecases:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
Hope this helps

How to add callback to AJAX variable assignment

I've got a variable responce which is assigned via an AJAX function send(). When I make the assignment...
responce = send();
response returns before send does giving me back an undefined how can I add a callback to prevent this from happening?
EDIT: a clarification on what I'm asking..
It's still returning undefined. I'm assigning the variable with the function send send returns onreadystatechange however when my code is executing.. response returns as undefined before send() can return. How do I stop the code under response from running on till response has been assigned sends value?
EDIT2:
The following code is my send function...
function send(uri)
{
var xhr = new XMLHttpRequest();
xhr.open("POST",uri,true);
xhr.onreadystatechange = function (send){
if(xhr.readyState == 4){
return xhr.responseText;
}
}
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
xhr.send(null);
}
You are using Ajax in a asynchronous manner, but you are treating it to be synchronous.
Asynchronous calls goes off to do its job while the rest of the code after the initial send call executes. You are getting undefined because the code is not returning anything.
If you look at the XMLHttpRequest object, the 3rd argument in the open method is the asynchronous flag.
open("method", "URL"[, asyncFlag[, "userName"[, "password"]]])
Setting it to true [default is left off] will make an asynchronous call. Setting it to false will make it synchronous.
The problem with using synchronous calls is it locks up the user's browser until the call is returned. That means animated gifs stuff, browser timers stop, and so on. If the server takes forever to respond, the user can not do anything.
The best solution is to avoid using synchronous calls. Use the call back to continue the code execution flow.
So based on your edit, I will edit my response with a basic solution
function send(uri, callback)
{
var xhr = new XMLHttpRequest();
xhr.open("POST",uri,true);
xhr.onreadystatechange = function (send){
if(xhr.readyState == 4){ //You really should check for status here because you can get 400, 500, etc
callback(xhr.responseText);
//return
}
}
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
xhr.send(null);
}
function myFunction(){
var myUrl = "foo.php";
//show a loading message or soemthing
var someDiv = document.getElementById("loadingMessage");
someDiv.style.display = "block";
//Second half of your function that handles what you returned.
function gotData( value ){
someDiv.style.display = "none";
alert(value);
}
send(myUrl, gotData);
}
If you really want to do synchronous and you do not mind locking up a user's browser
function send(uri, callback)
{
var xhr = new XMLHttpRequest();
xhr.open("POST",uri,false);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
xhr.send(null);
if(xhr.status==200){
return xhr.responseText;
}
else{
return null;
}
}
I presume you are talking about the XMLHTTPRequest.send() method, rather than a framework's wrapper.
send does not return anything. It will always return undefined.
To get the HTTP response, you need to monitor onreadystatechange, as countless StackOverflow answers and internet tutorials (e.g. this one) demonstrate.
you must assign the value to your response on readystatechange event of your request, something like this:
req.onreadystatechange = function(){
if (req.readyState===4) { // checks if data is already loaded.
callback(req.responseText,req.status); //call your callback function with response and status as parameters.
}
};
try this:
function send(uri, callback)
{
var xhr = new XMLHttpRequest();
xhr.open("POST",uri,true);
xhr.onreadystatechange = function (send){
if(xhr.readyState == 4 and callback){
callback();
}
}
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
xhr.send(null);
}
send("uri here", function(){
//whatever needs to be done after request
})

Javascript: XMLHttpRequest Task Switch

document.getElementById('contactButton').value = "Sending";
xmlhttp.onreadystatechange=stateChanged;
xmlhttp.open("GET",url,false);
xmlhttp.send(null);
function stateChanged(){
if (xmlhttp.readyState==4) {
var response = xmlhttp.responseText;
if(response == "true"){
document.getElementById('contactButton').value = "Sent :)";
}
}
When running this javascript, contactButton never gets set to "Sending...". It hangs for one second, and then changes to "Sent :)".
I'm not real sure about the processing order of javascript, but it seems like it needs some sort of task switch to process the XMLHttpRequest().
This is obviously an abbreviated code, but I have several other javascript/css things I am trying to do before the xmlhttp. It seems like the xmlhttp just takes over when the request is sent.
Any ideas?
You're passing false to open, so it's running synchronously. That means it doesn't use the readyState and instead just delays until the request completes. If you want to do sync, it should be:
xmlhttp.open("GET",url,false);
xmlhttp.send(null);
if(xmlhttp.status == 200)
{
var response = xmlhttp.responseText;
document.getElementById('contactButton').value = "Sent :)";
}
You should change to async to avoid hanging your script, and you will probably find it easier to use a JavaScript library.

Categories

Resources