AJAX does not synchronously - javascript

I've got an issue similar to this question here:
Javascript and AJAX, only works when using alert()
I have an AJAX call to update a field in the database when finalizing a form. However, the call doesn't seem to be reaching the controller. When I put an alert in, it works. I've currently got it set to synchronous because of the issue, but even then, without the alert, it only reaches the controller about 1 in every 5 or six times. This is the AJAX bit:
function finalize() {
if (!confirm("Are you sure?"))
return;
$("#finalizebutton").attr('disabled', 'disabled');
var request = new XMLHttpRequest();
var url = "/Operation/Finalize/";
request.open("GET", url, false);
request.send();
$("#otherformstuff").attr('disabled', 'disabled'); //a few disable calls
}
On the control side I have approximately:
public ActionResult Finalize()
{
db.setfinalized(true); //breakpoint here that only gets hit about 1 in 5 tests
return Content("Finalized");
}
Even when there is an alert shoved in there it sometimes doesn't work.
Oddly enough, I put an alert for request.responseText and it gave me the response from the control without the control ever actually processing it...
Any thoughts on this are appreciated.

Because you tell it to be synchronous.
Your problem is with this line:
request.open("GET", url, false);
The open method takes 3 arguments. Method, url, and the third is a boolean that tells it whether or not the request should be asynchronous.
Just change the false to true, and the request will be async.
request.open("GET", url, true);
But you could also just replace that entire block of XHR code with this one line..
$.get('/Operation/Finalize/');

Related

javascript AJAX call causing a timing problem

Program A has a form which submits to program B. The program A form has an input :
<input type = 'hidden' name = 'token' id = 'token' value = ''>
The value is set in a javascript function tkn() which is called by program A. The call:
<input type = 'button'
value = 'continue'
onclick = 'tkn()'>
The function tkn() calls an API function which returns the token. A callback function handles success or failure of the call. If there is success the callback executes
document.getElementById('token').value = response.id;
and then submits program A
var theform = document.getElementById('token');
alert('theform is ' + theform);
theform.submit();
Note the alert, which was put in there while I was debugging, to make sure the form was properly picked up before being submitted.
As long as the alert is there, everything is fine. Program A is submitted to Program B, the token goes through to B and does whatever it is supposed to do.
However, if the alert is not there, the procedure fails, because the token is passed through to program B as a blank.
I found an explanation of the problem here, along with a solution I don't understand: function not working correctly unless there is an alert . Apparently it is a timing problem because AJAX is asynchronous. The alert gives the AJAX call time to complete.
He suggests that the solution is to provide a callback where "you will perform the necessary actions". I have a callback function, but I don't know what are the "necessary actions" it should take to ensure that the AJAX call completes. Here is the callback:
function tokenHandler( status, response ){
// (ie. if the "error" key exists in the response).
if (response.hasOwnProperty( "error" )){
alert( "Something went wrong! + response.error.message);
return;
}
else{
document.getElementById('token').value = response.id;
}
}//function tokenhandler
Can someone enlighten me about what "necessary actions" the callback function should take to make sure the AJAX call is complete?
In the comments it is suggested that putting the
document.getElementById('token').value = response.id;
in the callback is the correct thing, because we only get to the callback if the AJAX response is complete. Well, that's where the line of code it -- in the callback function. So maybe the problem isn't an AJAX timeing problem. But it sure is true that the thing won't run without that alert.
Does anyone have any other suggestions?
API call:
Stripe.createToken(
{
number: cardno,
exp_month: emth,
exp_year: eyr,
cvc: cvv,
address_zip: '19004'
},
amount,
tokenHandler,);
A SOLUTION HAS BEEN FOUND. I put the submit into the callback function instead of in the main tkn() function. That fixed the problem. So after all it is a timing problem, but I think it is between the callback function and the main function. I assumed the submit wouldn't happen until the callback was finished, but apparently that is not the case.
In the SO link you gave us, the answer says that the alert() paused the code. This makes the code work because AJAX does not run synchronously, which means the code does not wait for the AJAX call to finish. Therefore, the code and the AJAX run together and the AJAX hasn't given back the result when your code finishes running. But, alert()s stop the code from running temporarily until you click done, so the AJAX has time to finish.
Please add all of your JS code so I can see how it can be fixed. I will edit this once you do it.
You need to put your code inside the AJAX callback. Example:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Code here
}
};
xhr.open("GET", "filename", true);
xhr.send();
Maybe you could delete your onclick and add an event listener in the // Code here. Example:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("YourInput").addEventListener("click", function() {
var theform = document.getElementById('token');
alert('theform is ' + theform);
theform.submit();
});
}
};
xhr.open("GET", "filename", true);
xhr.send();

XMLHttpRequest - execute operation on webservice

I am able to connect to the webservice. That service has a number of operations that can be executed and return a result. One is called helloWorld. I would like to perform that operation. Right now I specify the web service file, but i need to further specify the method in the file to be executed. Here is what I have:
function soapReq() {
var ajaxRequest = new XMLHttpRequest();
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
// Get the data from the server's response
console.log(ajaxRequest.responseText);
}
}
ajaxRequest.open('POST', 'http://theWebServiceNameThatICannotGiveOut', true);
ajaxRequest.send(null);
}
Can I add the operation to be performed onto the end of the url or something?
You should find something on the server, or find the page that has the hello world operation. Then you can make a request to that page (see example below), and you don't need it to be a POST request, just use GET.
Example:
// something like this:
ajaxRequest.open('GET', 'http://site.xxx/helloWorld.php', true);
// or this
ajaxRequest.open('GET', 'http://site.xxx/helloWorld.php?somevar=somevalue', true);
// or also this
ajaxRequest.open('GET', 'http://site.xxx/somepage.php?op=helloWorld', true);
But I can't help you more than this if you can't provide the site you're trying to make the request to. You should ask someone that works on it or search on the site itself.

Understand Ajax XMLHttpRequest in details

I am new to Ajax, and to make things worse, also a Javascript noob, and I have posted the bellow code of a chat script, to retrieve text from db, in real time, and the code is working, but I need to understand what certain requests are all about.
<script>
function retrieve(){
var xmlhttp;
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest(); }
else if(window.ActiveXObject) {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
else {
alert('Please update your browser to start chatting');
}
Simply, I understand the above is (I created it) just a function with global variable declared to be assigned whether XMLHttpRequest/ActiveXObject Object is declared depending if browser is IE6,7 and others if not throw in alert...
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
document.getElementById("canvas").innerHTML = xmlhttp.responseText;
}
}
Similarly, the above I assume takes the onreadystatechange property of the Ajax API and checks for it's state, readyState & status which, if only they match 4 and 200 means, Ajax is working as wanted
t = setTimeout("retrieve()", 2000);
I know the setTimeout() is a bit like setInterval() function, which runs the function inside it, every 2 seconds, to check for new messages.
xmlhttp.open("GET", "getajax.php", true);
xmlhttp.send();
Now, the problem is with the above, I can almost understand that the .open method is supposed to get data from getajax.php even though, I have no idea of what true means in this instance, but as far as the xmlhttp.send(); I have absolutely no clue,
So, All I need is for you to explain to me what I have missed during my illaboration, and
what the last queries mean, just in brief.
}
retrieve();
</script>
<div id="canvas"></div>
xmlhttp.open("GET", "getajax.php", true);
xmlhttp.send();
true is what tells the request to be performed A -synchronously, which is the A in AJAX. Then finally .send() actually send the request.
Asynchronous requests are non-blocking meaning that the rest of your code wont wait for them to finish and return before continuing. That is why you sent event handlers before starting the request via xmlhttp.onreadystatechange. That way once the request is complete you have already told your script what to do with the returned information.
Hope this helps.
Edit Additionally I recommend using some sort of framework or library for javascript like jQuery. While it is good to learn some of the javascript core, something like jQuery will make your life much easier.
Simply, I understand the above is (I created it) just a function with global variable declared to be assigned
xmlhttp isn't a global. It's a local variable in the global function retrieve.
Similarly, the above I assume takes the onreadystatechange property of the Ajax API and checks for it's state
onreadystatechange is a property that accepts a function. That function is run when the value of readyState changes. That function is usually used to check the status of the request.
I know the setTimeout() is a bit like setInterval() function, which runs the function inside it, every 2 seconds, to check for new messages.
setTimeout is like setInterval in a sense that it runs a function at a later time. Unlike setInterval, it only runs the code once. Also, that's not the proper way of running a timer. Here's a post that explains how to properly use timers.
the .open method is supposed to get data from getajax.php even though, I have no idea of what true means in this instance, but as far as the xmlhttp.send(); I have absolutely no clue
The open builds your request by accepting:
The type of request (GET/POST)
The url where you want the request sent
The third argument determines if the request is asynchronous or not.
If set to false, this makes the request synchronous. The browser will freeze and wait for the response.
If true, the request us asynchronous. The browser will not freeze in waiting.
The default value is true, so you can omit it.
send is the actual function that ultimately sends the request to the server.
For further reading, I suggest you read MDN's section regarding AJAX.

Javascript block on AJAX load

I am looking for a way to make an AJAX load request in javascript, but have the javascript code pause execution while waiting for the AJAX load to complete. In other words, I am trying to do a synchronous AJAX load request (I know the 'A' in AJAX stands for asynchronous. I'm just hoping maybe the name isn't exactly right.) . What I have is
$('#my_id').load("my_page.pl?my_param=p1&my_other_param=p2");
//Please wait here
//Now do stuff after load is complete.
The reason I want the request to be synchronous is because it creates an HTML table, and then the javascript which follows parses the table.
jQuery's 'load()' method takes a callback. Callbacks are generally how async code handles the "waiting" feature you want.
$("#my_id").load("my_page.pl?my_param=p1&my_other_param=p2", function (response) {
// do this stuff, which will run after the request is complete
});
That looks like jquery... I can't be sure because I don't know jquery at all but if so you might get better answers tagging it as such.
I can tell you that javascript has it's own method for synchronous OR asynchronous calls. This is what I use:
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// Use the activeX object for old IE
xmlhttp.open("GET","http://some.internet.address/woot?foo=bar", false);
// The third argument in the open function determines the asynchronous nature,
//it was set to false, so the code will halt at the send() point while the request is executed.
xmlhttp.send();
// Now, if the call succeeded...
if (xmlhttp.status==200) {
response = eval('('+xmlhttp.responseText+')');
// ...save the results to an object named response...
}
else {
// ...Otherwise do some other stuff
errorFunction(xmlhttp.status);
}
Lots of good info is also available here -
http://www.w3schools.com/ajax/ajax_xmlhttprequest_send.asp

what is the right way to manage multiple ajax requests?

We've all seen some examples in AJAX tutorials where some data is sent. They all (more or less) look like:
var http = createRequestObject(); // shared between printResult() and doAjax()
function createRequestObject() { /* if FF/Safari/Chrome/IE ... */ ... }
function printResult()
{
if (http.readyState == 4) { ... }
}
function doAjax() {
var request = 'SomeURL';
http.open('post', request);
http.onreadystatechange = printResult;
data = ...; // fill in the data
http.send(data);
}
// trigger doAjax() from HTML code, by pressing some button
Here is the scenario I don't understand completely: what if the button is being pressed several times very fast? Should doAjax() somehow re-initialize the http object? And if if the object is re-initialized, what happens with the requests that are being already on air?
PS: to moderator: this question is probably more community-wiki related. As stated here (https://meta.stackexchange.com/questions/67581/community-wiki-checkbox-missing-in-action) - if I've got it right - please mark this question appropriately.
Since AJAX has asynchronus nature, with each button click you would raise async event that would GET/POST some data FROM/TO server. You provide one callback, so it would be triggered as many times as server finishes processing data.
It is normal behaviour by default, you should not reinitialize of http object. If you want to present multiple send operation you have to do that manually (e.g. disabling button as first call being made).
I also suggest to use jQuery $.ajax because it incapsulate many of these details.
Sure that numerous libraries exist nowadays that perform a decent job and should be used in production environment. However, my question was about the under-the-hood details. So here I've found the lamda-calculus-like way to have dedicated request objects per request. Those object will obviously be passed to the callback function which is called when response arrives etc:
function printResult(http) {
if (http.readyState == 4) { ... }
...
}
function doAjax() {
var http = createRequestObject();
var request = 'SomeURL';
http.open('get', request);
http.onreadystatechange = function() { printResult(http); };
http.send(null);
return false;
}
Successfully tested under Chrome and IE9.
I've used a per-page request queue to deal with this scenario (to suppress duplicate requests and to ensure the sequential order of requests), but there may be a more standardized solution.
Since this is not provided by default, you would need to implement it in JavaScript within your page (or a linked script). Instead of starting an Ajax request, clicking a button would add a request to a queue. If the queue is empty, execute the Ajax request, with a callback that removes the queued entry and executes the next (if any).
See also: How to implement an ajax request queue using jQuery

Categories

Resources