I'm creating XMLHttpRequest as follows:
function checkDependencyFormFilledStatus(appName,formName){
var xmlhttp;
xmlhttp=new XMLHttpRequest();
xmlhttp.open("GET","checkFormDependency.action formName="+formName+"&applicationName="+appName,false);
xmlhttp.send();
var dependentFormEmptyStatus = Ext.JSON.decode(xmlhttp.responseText);
alert(xmlhttp.responseText);
return dependentFormEmptyStatus;
}
The response returned by the object is dependent on the database which the action class is using.
This works fine in Firefox 10.0.
But for IE7, it returns correct response only for the first time. And for the rest of the function calls, it returns the same response (no matter what changes we make in the database). It updates its response only when I close the tab and open it (not even on reloading the page).
How to make it work in IE 7?
Sounds like the response is being cached.
Add a psuedo-random string (e.g. a timestamp) to the end of the URI to cache burst.
you are simply having a caching issue with IE7, as it caches the XMLHttpRequest() after it created it and store it in its memory. even with subsequents xmlhttp=new XMLHttpRequest(); the variable don't get any assigment because it already has an instance (from your first xmlhttp=new XMLHttpRequest(); ) .
what you need to do is to invalidate and destroy your XMLHttpRequest request after every use.
you first create your XMLHttpRequest (for msie 7) like this:
function createXMLHttpRequest(){
var xmlHttp = null;
if(typeof XMLHttpRequest != "undefined"){
xmlHttp = new XMLHttpRequest();
}
else if(typeof window.ActiveXObject != "undefined"){
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP.4.0");
}
catch(e){
try {
xmlHttp = new ActiveXObject("MSXML2.XMLHTTP");
}
catch(e){
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e){
xmlHttp = null;
}
}
}
}
return xmlHttp;
}
so to create it each time in the function you want to use.
function checkDependencyFormFilledStatus(appName,formName){
if(xmlHttp_global){
xmlHttp_global.abort(); // abort the current request if there's one
}
// Create the object each time a call is about to be made
xmlHttp_global = createXMLHttpRequest();
if(xmlHttp_global){
xmlHttp_global.onreadystatechange = myCallbackFunction; // make you callback thing here
xmlHttp_global.open("GET","checkFormDependency.action formName="+formName+"&applicationName="+appName,false);
xmlHttp_global.send(null);
}
}
in your callback ("onreadystatechange" function) you delete it after using it
function myCallbackFunction()
{
if(xmlHttp_global && xmlHttp_global.readyState == 4){
//do your thing here and ... or nothing
var dependentFormEmptyStatus = Ext.JSON.decode(xmlhttp.responseText);
alert(xmlhttp.responseText); // like this for example?
xmlHttp_global = null; //delete your XMLHTTPRequest
}
}
so IE 7 will find each time an empty reference and will have the need to recreate it again for each use.
if you don't want to create and delete it eacht time you simply play with some HTTP-Headers in your XMLHTTPRequest
xmlHttp_global.setRequestHeader("If-Modified-Since", "Thu, 1 Jan 1970 00:00:00 GMT");
xmlHttp_global.setRequestHeader("Cache-Control", "no-cache");
like suggested here
Another alternatives include:
Using POST method over GET method
xmlHttp_global.open("POST","checkFormDependency.action",false);
xmlHttp_global.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // or another content type , its up to you
xmlHttp_global.send("formName="+formName+"&applicationName="+appName);
Using a "dummy" variable in your query-String to burst out the cacher of IE(7,6)
xmlHttp_global.open("GET","checkFormDependency.action formName="+formName+"&applicationName="+appName+"randomVar="+Math.Random(),false);
Links
XMLHTTPRequest cache in IE 7 and 6
Related
I'm trying to use AJAX for the first time and I've encountered an issue. I didn't manage to resolve it by reading tutorials.
I have a PHP file on my server which echoes the correct output when I access the file directly. However when I try accessing it through a HTML. Here is my javascript code:
var httpRequest;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 8 and older
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
httpRequest.open('GET', 'http://www.mysite.com/myfile.php?variable1=' + variable1 + "&variable2=" + variable2, true);
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState === 4) {
var receivedString = httpRequest.responseText;
console.log(receivedString);
} else {
console.log(httpRequest.readyState);
}
};
nothing happens; neither receivedString nor the value of httpRequest.readyState is output. What could be the reason?
Append httpRequest.send(null); to your code.
The request is not sent to the server until the send method is called, so the readyState property does not change and the onreadystatechange event is not fired.
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.
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()
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()
I'm new to Ajax and this has me stumped. It's relatively simple but trips up on the onclick handler with the first xhr.open(). Firebug says it's not a function, my guess is the XMLHttpRequest object isn't being created, but I'm not sure. Anyone have any ideas?
Thanks in advance.
function init(){
function getXMLHTTP(){
var xhr = false;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
return xhr;
}
function updatePage(theData){
$('results').innerHTML = theData; //TODO: pretty this up with mootools
}
var xhr = getXMLHTTP();
if (xhr) {
xhr.onreadystatechange = function(){
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var theData = xhr.responseText;
updatePage(theData);
}
else{
alert("Error communicating to web service!");
}
}
}
$('submit_btn').onclick = function(xhr){
if ($('state').value != "") {
var theValue = $('state').value;
xhr.open("GET", "/inc/calc.php?state="+theValue, true); //Ajax 101: 3rd argument marks object as asynchronous
xhr.send(NULL);
}
else if ($('city').value != "") {
xhr.open("GET", "/inc/calc.php?city="+$('city').value, true);
xhr.send(NULL);
}
else if ($('county').value != "") {
xhr.open("GET", "/inc/calc.php?county="+$('county').value, true);
xhr.send(NULL);
}
else {
//the form is empty, or just down payment is filled. returns whole freakin' table.
xhr.open("GET", "/inc/calc.php", true);
xhr.send(NULL);
}
}
}
}
The problem with your code is the onclick function. You have put the xhr in the argument list to the function. Remember that when a function is called, the value of this variable is set by the caller. In this case it would be the event dispatcher, and it would probably set the xhr variable to an event object, which does not have an open function.
If you remove the xhr variable from the argument list of the onclick function, then it will look for the xhr variable in the parent scope, the global scope, and it will find it there, and it should work. I haven't tested it though.
I'm assuming you are using some kind of framework as well (judging by the frequent use of $, and the reference to mootools). This framework probably has an ajax function built in, as well as a cross browser event model. Try using it instead, you will run into a lot less problems.
When assigning the onclick handler you create a new function that takes a parameter called xhr:
$('submit_btn').onclick = function(xhr){
...
xhr.open("GET", "/inc/calc.php?state="+theValue, true);
...
}
The click on the button won't pass a XMLHttpRequest object the the handler, so xhr will not have an open() method. The global definition of xhr doesn't matter because it's shadowed by the local parameter definition.
Generally you should just generate a new local XMLHttpRequest object when you need it, not try to use a global one. For example use an onclick function that creates a new local XMLHttpRequest:
$('submit_btn').onclick = function(){
var xhr = getXMLHTTP();
xhr.open("GET", "/inc/calc.php?state="+theValue, true);
...
}