Second request receives the first one that was still processing - javascript

I have a request system where two unrelated functions are making requests to my server. But the problem is the response is not correct let me explain what is happening step by step:
A background function makes a request to the server
Server processes task 1
A second unrelated background function makes a request to the server
Client recieves response of task 1
The second function recieves that response that was for the first function.
The first function never gets a response.
Now i don't know how to solve it, but i know i need to distinguish them separately so theres no conflictions here.
This is my current code that handles the request stuff:
function call_back(result,func){
if(typeof(func) != 'undefined' || func != false){
func(result);
} else {
return false;
}
}
function caller(url,cfunc){
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
else
{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=cfunc;
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
function call_file(url,func){ //handles html files (not json_encoded)
caller(url,function(){
if ( xmlhttp.readyState== 4 && xmlhttp.status== 200 ){
call_back(xmlhttp.responseText,func);
}
});
}
function call_data(url,func,JsonBool){ //handles json_encoded data
caller(url,function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
call_back(JSON.parse(xmlhttp.responseText),func);
}
});
}
What can i do to my functions, for preventing this behaviour?

Here is an example of how you could structure your code - I have used this, it works, but it could be refined.
function Ajax(url, callback,args){
var xhttp = init();
xhttp.onreadystatechange = process;
function init() {
if(window.XMLHttpRequest)
return new XMLHttpRequest();
else if (window.ActiveXObject)
return new ActiveXObject("Microsoft.XMLHTTP");
}
function process() {
if (xhttp.readyState==4 && xhttp.status==200) {
if (callback) callback(xhttp.responseText,args);
else return xhttp.responseText;
}
}
this.Get=function(){
xhttp.open("GET", url, true);
xhttp.send(null);
}
}
To use it:
var url = '/someurl';
var ajax = new Ajax(url,yourCallback,parameters);
ajax.Get();
I believe DRobinson was talking about something like this but more robust. This should be a good example to get you started though.

It looks to me as though you're using a global/window variable for xmlhttp. If this is the case, certain parts of the second call will overwrite the first. Consider using an Object Oriented approach, or otherwise instantiating these as vars in different scopes.

Related

javascript worker loop ajax

I am having a worker which has an array of urls. I loop through these URLs and throw an AJAX call, but inside success method of ajax when I send message back to website, it always sends the last request.
app.js
var worker = new Worker('worker.js');
var urls = ['url1','url2','url3'];
worker.addEventListener('message', function(e) {
console.log('Worker: ', e.data.url);
}, false);
worker.postMessage({"args":[urls]});
worker.js
self.addEventListener('message', function(e) {
function load(url){
var xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
console.log(xmlhttp);
self.postMessage({'url':url});
}
}
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
var urls = e.data.args[0];
for(var i = 0; i<urls.length; i++){
load(urls[i]);
}
}, false);
Now inside console.log(); of app.js, the output is only of the last url.
I don't get all all URLs response.
Can anyone help ?
The answer is real easy. make line 3
var xmlhttp=new XMLHttpRequest();
What you're doing now, is setting xmlhttp as a global variable. This means overriding the variable every time line 3 is executed.

Java Script Function not returning value from Ajax request [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I have following AJax request function which is working fine. upon successful it returns 1 else 2.
Now i would like to perform some action outside of this function based on this return value, as below, but its not working .. it always returns "undefined"...
I expect the return_code should return either 1 or 2 based on following code
<script>
var return_code=add_to_cart_ajax(200);
alert(return_code);
</script>
returns "undefined"
AJAX Request :
<script>
//Ajax to send request to add
function add_to_cart_ajax(id)
{
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
alert(xmlhttp.responseText); // returns 1
if (xmlhttp.responseText==1)
{
return 1;
}
else
{
return 2;
}
}
}
xmlhttp.open("GET","add.php?id="+id,true);
xmlhttp.send();
}//end of the function..
</script>
Since an AJAX call is asynchronous one common way of dealing with it is to use a callback-function that gets called once the request is processed.
Something like
<script>
add_to_cart_ajax(200, function(return_code) {
alert(return_code);
});
</script>
<script>
//Ajax to send request to add
function add_to_cart_ajax(id, callback) {
...
alert(xmlhttp.responseText); // returns 1
if (xmlhttp.responseText==1) {
callback(1);
} else {
callback(2);
}
...
}//end of the function..
</script>
EDIT: If you need to hang on to the return_code, you'd do
<script>
var return_code;
add_to_cart_ajax(200, function(result) {
return_code = result;
});
</script>
But it's important to understand that since the AJAX request is asynchronous, your return_code variable will not have a value assigned to it untill the AJAX request is fulfilled and you can't use it for anything untill that has happened, so any code that needs to do something with return_code should be included in or called from the callback. This is one of the things that is going to be a bit hard to grasp at first if you're coming from a background where all code is being run top-to-down. That's simply not the case once you start working with asynchronous stuff.
Seeing that an ajax call is async, you can't expect to have the result in your alert(return_code); because effectively at that time the ajax call has not get the response yet.
Could be useful to give a look at how libraries as jQuery or Zepto have done as well as implementing something following "promise" logic, just to avoid the callback hell.
ok i will try to make an example:
if you order a package on amazon and you want to unpack this in the next step
orderPackage();
unpackPackage(); // undefined / exception, because you have to wait for the package to be arrived
try not to return a value with the "onreadystatechange". you can call another function from inside this method or you can set global variables. as example:
Just to explain how ajax works (DO NOT USE THIS PEACE OF CODE, SCROLL DOWN FOR BETTER SOLUTION!):
ajaxReturn = null;
function add_to_cart_ajax(id) {
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
ajaxReturn = xmlhttp.responseText;
}
}
xmlhttp.open("GET","add.php?id="+id,true);
xmlhttp.send();
while(ajaxReturn == null) {
//waiting for response
//will break if the request is finished
}
alert(ajaxReturn);
}//end of the function..
Please not use this in productive because the while will cause the browser to stop i think.
but this should explain the behaviour to you.
Right Solutions
// This will send an ajax-request and execute the fCallback if finished
// #param sUrl - Url to send the request to
// #param fCallbackSuccess - method that will be executed on successfull request
// #param fCallbackFailed - method that will be executed on failed request
// #param bAsync - will make the request async or sync
function ajax(sUrl, fCallbackSuccess, fCallbackFailed, bAsync) {
if (window.XMLHttpRequest) {
oXmlHttp=new XMLHttpRequest();
} else {
oXmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
oXmlHttp.onreadystatechange=function() {
if (oXmlHttp.readyState==4 && oXmlHttp.status==200) {
fCallbackSuccess.apply(oXmlHttp);
return;
}
fCallbackFailed.apply(oXmlHttp);
}
oXmlHttp.open("GET", sUrl, bAsync);
oXmlHttp.send();
}
//usage example:
var fSuccess = function(oXmlHttp) {
//do something with oXmlHttp
alert(oXmlHttp.responseText);
}
var fFailed= function(oXmlHttp) {
//do something with oXmlHttp
alert('Request failed!');
}
ajax("add.php?id="+id, fSuccess, fFailed, true);
have a nice day

How to do a request to the server and liberate JavaScript to continue processing

Is there a way to make a request and liberate JavaScript and HTML to do their own thing, leaving the Server to do its thing until it completes, at which point an event grabs control of JavaScript, dumps the data to a designated receiving end and ends the call?
I use this method for calling Python
function par_makeHttpObject() {
try {
return new XMLHttpRequest();
}
catch (error) {}
try {
return new ActiveXObject("Msxml2.XMLHTTP");
}
catch (error) {}
try {
return new ActiveXObject("Microsoft.XMLHTTP");
}
catch (error) {}
throw new Error("Could not create HTTP request object.");
}
And I call it as follows:
...
var request = par_makeHttpObject();
request.open("POST", "../getFdList?Fds=allFds", false);
request.send();
var dta = request.responseText.split("\n");
var cnt = 0;
for (var x in dta) {
try {eval(dta[x]);}
catch (error) {alert("JS Error - check JS part of syntax!\n" + dta[x]);}
}
...
The problem is that JavaScript sits and waits for a reply to the request and the user could be doing something else. Some calls take 5 minutes...
Any ideas would be appreciated.
DK
Use jQuery's ajax() function instead of rolling your own AJAX solution. ajax() defaults to asynchronous requests, so you can pass it a function that is called on request completion:
$.ajax({
type: "POST",
url: "../getFdList?Fds=allFds"
}).done(function( msg ) {
alert( "Response: " + msg );
});
That way, you can call ajax(), give it your callback function, and carry on with whatever other processing you need to do.
Another plus for jQuery is that it's pretty well cross-browser without any effort.
Yes, it's very easy in fact. Change the last parameter in your open call to "true":
(I pulled this from w3schools(Yes I'm aware of the sites bad rep, this is just an example))
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
//THIS IS WHERE YOU GET THE SERVER RESPONSE
var response = xmlhttp.responseText;
}
}
xmlhttp.open("GET","ajax_info.txt",true);
xmlhttp.send();
}
The best part about AJAX is the ability to continue working on something else while the HTTP request is being made asynchronously.
$.post('../getFdList?Fds=allFds', {}, function(response) {
var dta = response.split("\n");
// ...
}, 'text');
// continue doing something else here
See also: $.post()

Get Ajax function to return true or false

I'm trying to get an Ajax function to return true or false (it's a sort of validation function which is called from another function). So the other function needs to get a true or false value from this one so it would know what to do next.
I'm sure I've done this before but I can't get it to work now. I tried synchronous and asynchronous calls, having the return inside the onreadystatechange function and underneath it, and nothing.
This is the Ajax:
function saveBooking(){
var service_ids=document.getElementById("allservice_ids").value;
var provider_ids=document.getElementById("allprovider_ids").value;
var chosen_time=document.getElementById("chosen_time").value;
var chosen_date=document.getElementById("chosen_date").value;
var message=document.getElementById("message").value;
var parameters="service_ids="+service_ids+"&provider_ids="+provider_ids+"&time="+chosen_time+"&date="+chosen_date+"&you=<?php echo $_SESSION['user_mail']; ?>&message="+message
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("POST","include/save_booking.php",true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
xmlhttp.onreadystatechange = function() {//Call a function when the state changes.
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var yesorno=xmlhttp.responseText;
if(yesorno=="ok"){
return true;
}
else{
document.getElementById("booking_error").innerHTML = xmlhttp.responseText;
return false;
}
}
}
xmlhttp.send(parameters);
}
Right now save_booking.php just contains the line <?php echo "ok"; ?>, I reduced it to that for testing purposes.
Can someone tell me how to get this to work? In the other function, if I do this:
if(saveBooking()){
alert(saveBooking());
}
It just alerts the word 'undefined'.
Please note that I am not too familiar with jQuery, so 'use jQuery' is not a helpful response for me.
Your current return statements only determine what the onreadystatchange method returns, which is not handled (correct me if I'm wrong - at least I wouldn't know how to access its return value). What you want is to influence the return of saveBooking, so you could do something like this:
var responseOk = false;
xmlhttp.onreadystatechange = function() {//Call a function when the state changes.
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
responseOk = (xmlhttp.responseText=="ok");
if(!responseOk) {
document.getElementById("booking_error").innerHTML = xmlhttp.responseText;
}
}
}
...
return responseOk;
By the way, unless there's some special reason why you want to avoid jQuery (e.g. I personally like to learn to do things myself first), I strongly suggest you take a look at it. It's not going to be complicated for you and will make things a lot easier.
Apart from this I have to support MilkyWayJoe's comment - it does not make much sense to generate an asynchronous HTTP request and then require to wait for its return value. At the moment, my above example would probably return false in most cases because the request is not finished by the time the script arrives at the return statement. It makes sense not to mix up the function making the request and the callback of the request.

Ajax response works after two clicks?

I just wrote a basic user-login system where the html page uses javascript to send the ajax request to a servlet which accesses through database.
Here's the js code
var res;
function getXMLObject()
{
var xmlHttp = false;
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP") // For Old Microsoft Browsers
}
catch (e) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP") // For Microsoft IE 6.0+
}
catch (e2) {
xmlHttp = false // No Browser accepts the XMLHTTP Object then false
}
}
if (!xmlHttp && typeof XMLHttpRequest != 'undefined') {
xmlHttp = new XMLHttpRequest(); //For Mozilla, Opera Browsers
}
return xmlHttp; // Mandatory Statement returning the ajax object created
}
var xmlhttp = new getXMLObject(); //xmlhttp holds the ajax object
function handleServerResponse() {
if (xmlhttp.readyState == 4) {
res=xmlhttp.responseText;
}
else {
return false;
alert("Error during AJAX call. Please try again");
}
}
function ajaxFunction() {
var veid=document.getElementById("eid").value;
var vpwd=document.getElementById("pwd").value;
//window.alert('here inside ajaxFunction'+vconf+' '+vseid);
if(xmlhttp) {
xmlhttp.open("GET","check_login?eid="+ veid +"&pwd="+ vpwd,true); //this is the servlet name
xmlhttp.onreadystatechange = handleServerResponse;
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlhttp.send(null);
}
}
function def()
{
//window.alert('hi');
ajaxFunction();
//alert('res:'+res);
if(res=='y')
{
return true;
}
else
{
document.getElementById("uhidden").style.color="#CC0000";
document.getElementById("uhidden").innerHTML="Invalid E-Mail ID or Password"
return false;
}
}
But the code works only after two clicks :(
Any help guys?
Your def function calls ajaxFunction and then straight away checks the res variable. However ajaxFunction just sends the AJAX request; it does not wait for the AJAX response to arrive. Your code is checking the res variable before it is being set from the AJAX response.
This is why it works on the second click - not because the res variable is being set by the second click's AJAX response, but because it is still set from the first click's AJAX response.
The solution is to re-arrange your code a bit. Move the code to display the invalid login message to where the AJAX response is received. In other words, replace the res=xmlhttp.responseText; line with some code to check if xmlhttp.responseText is not y and display the invalid login message.
I guess you call def()
Your Request ist asynchron(because you set the 3rd argument of open() to true ), but in def() you immediately after sending the request work with the the result:
ajaxFunction();
//alert('res:'+res);
if(res=='y')
At this time the request usually is not finished, the result not available yet
Put all code that has to work with the server-response into handleServerResponse()

Categories

Resources