I am trying to create a Firefox extension that can run multiple XMLHttpRequests per page. The code is below (my main function calls the makeRequest on different URLs). My problem is that it always returns (at the "alert('Found ...')" for debugging purposes) the same URL instead of displaying the different responses. I think the issue is that I should somehow pass the http_request instance to the alertContents() function instead of just using http_request directly, but not sure how or if this is correct. Thank you.
function makeRequest(url,parameters) {
http_request = false;
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = alertContents;
http_request.open('GET', url + parameters, true);
http_request.send(null);
}
function alertContents() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
alert('Found: ' + http_request.responseText);
} else {
alert('There was a problem with the request.');
}
}
}
Your problem is you've only got one http_request identifier which is reused every time the makeRequest function is called. Here is one simple adjustment:-
function makeRequest(url,parameters) {
var http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = function() {
alertContents(http_request)
};
http_request.open('GET', url + parameters, true);
http_request.send(null);
return http_request;
}
function alertContents(http_request) {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
alert('Found: ' + http_request.responseText);
} else {
alert('There was a problem with the request.');
}
http_request.onreadystatechange = fnNull;
}
}
function fnNull() { };
The http_request identifier is local to each makeRequest execution. The correct instance of XHR is then passed to alerrContents each time onreadystatechange is fired by using a capture.
BTW, why separate url from parameters? Since the caller has to ensure the parameters argument is correctly url encoded it doesn't seem like a very useful abstraction. In addition the caller can simply pass a URL containing a querystring anyway.
this function can be further improved with cross browser functionality:
function makeRequest(method, url, parameters) {
var http_request = false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
// set type accordingly to anticipated content type
http_request.overrideMimeType('text/xml');
//http_request.overrideMimeType('text/html');
}
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = function() {
alertContents(http_request);
}
url += (method=="GET")?parameters:"";
http_request.open(method, url, true);
if (method == "POST") {
http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request.setRequestHeader("Content-length", parameters.length);
http_request.setRequestHeader("Connection", "close");
}
http_request.send((method=="GET")?null:parameters);
}
Yes, you should use the same XMLHttpRequest.
Infact, try using this code and see if it works :
function makeRequest(url,parameters) {
http_request = false;
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = function () {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
alert('Found: ' + http_request.responseText);
} else {
alert('There was a problem with the request.');
}
}
};
http_request.open('GET', url + parameters, true);
http_request.send(null);
}
In the code above, I simply attached the function directly to the onreadystatechange event .
Related
I've looked through answers but can't seem to find one that fixes this particular problem. Also a similar question is still unanswered.
I am using IE8 to send a XMLHttpRequest but it never gets sent. IE8 supports XMLHttpRequest objects, so why isn't it sending? (I can't use jQuery for this.)
My code:
window.onload = function() {
// Create the HTTP object
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
alert("couldn't load data");
}
var dataUrl = "./data2.json";
alert("sending");
xmlhttp.open("GET", dataUrl, true);
alert("sent");
xmlhttp.onreadystatechange = function() {
//ready?
if (xmlhttp.readyState != 4)
return false;
//get status:
var status = xmlhttp.status;
//maybe not successful?
if (status != 200) {
alert("AJAX: server status " + status);
return false;
}
//Got result. All is good.
alert(xmlhttp.responseText);
return true;
}
xmlhttp.send(null);
}
The alert('sent'); never gets called, but alert('sending'); does. How can I make this xmlhttp request work?
Edit: I've updated my code to include XDomainRequest for IE8. This gets me past the xmlhttp.open part, but now I'm getting an "Unspecified error" on the xmlhttp.send part.
edited code (Note: I changed my variable name from xmlhttp to xhr.):
window.onload = function() {
// Create the HTTP object
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
alert("couldn't load data");
}
var dataUrl = "./data2.json";
alert("sending");
if ("withCredentials" in xhr) {
// XHR for Chrome/Firefox/Safari
xhr.open('get', dataUrl, true);
}else if (typeof XDomainRequest != "undefined") {
// XDomainRequest for IE.
xhr = new XDomainRequest();
xhr.open('get', dataUrl);
alert("opened");
} else{
alert('CORS not supported');
};
xhr.onprogress = function () { };
xhr.ontimeout = function () { };
xhr.onerror = function () { alert('error'); };
xhr.onload = function() {
alert(xhr.responseText);
}
setTimeout(function () {xhr.send();}, 0);
}
alert('error'); gets called.
I am using an AJAX call within a javascript function to populate a SELECT input. This script does not work the first time but works as I intend it to each subsequent time that it is called. The relevant code follows:
function getXMLHttp()
{
var xmlHttp;
try
{
//Firefox, Opera 8.0+, Safari
xmlHttp = new XMLHttpRequest();
}
catch(e)
{
//Internet Explorer
try
{
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch(e)
{
try
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e)
{
alert("Your browser does not support AJAX!")
return false;
}
}
}
return xmlHttp;
}
function populateEntries(menu, userName, entryRow)
{
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if ((xmlHttp.readyState == 4) && (xmlHttp.status == 200) && (xmlHttp.responseText == ""))
{
window.alert("There are no records to view!"); }
else if ((xmlHttp.readyState == 4) && (xmlHttp.status == 200))
{
response = xmlHttp.responseText;
}
}
xmlHttp.open("GET", "getUsers.php", true)
xmlHttp.send(null);
ADDITIONAL UNRELATED CODE FOLLOWS ....
}
I've checked to see if the "response" is being passed from the AJAX call during the first function call and it is but it is not being passed out of the function for further use in the code that follows except on subsequent function calls. Can anyone tell me why this is happening? Your help will be very much appreciated. Before you tell me that this can be done with jquery, please understand that I need to do it with javascript.
I have a dynamic AJAX function which has many different modes (I call the function with different parameters and check via switch-case which mode has to be used) but when I call the AJAX function with different parameters directly one after another using the same XMLHttpRequest it seems that the second request overrides the first one.
Is that possible?
Here is a example for my function(EDIT):
$(function() {
ajax("test_1");
ajax("test_2");
});
function ajax(mode)
{
switch (mode)
{
case "test_1":
request = null;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else if (window.ActiveXObject) {
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {
}
}
}
if (!request) {
console.log("Kann keine XMLHTTP-Instanz erzeugen");
return false;
} else {
var url = "../ajax.php";
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
request.send('ajax_mode=test&request_mode=test_1');
request.onreadystatechange = function() {
if (request.readyState === 4)
{
interpretRequest_test_1();
}
};
}
break;
case "test_2":
request = null;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else if (window.ActiveXObject) {
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {
}
}
}
if (!request) {
console.log("Kann keine XMLHTTP-Instanz erzeugen");
return false;
} else {
var url = "../ajax.php";
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
request.send('ajax_mode=test&request_mode=test_2');
request.onreadystatechange = function() {
if (request.readyState === 4)
{
interpretRequest_test_2();
}
};
}
break;
}
}
function interpretRequest_test_1() {
if (request.status != 200) {
console.log("Error");
} else {
alert("1");
}
}
function interpretRequest_test_2() {
if (request.status != 200) {
console.log("Error");
} else {
alert("2");
}
}
Your request variable isn't defined using the var keyword, which makes it a global and thus you are reusing the same XHR object.
If you are reusing the same XMLHttpRequest object then yes, it will abort the previous request if you try to make another request with it, while the other request is in progress.
In your switch statements, define request with the var keyword. This makes the variable scoped to the local scope, and not a global.
switch (mode) {
case "test_1":
var request = null;
...
case "test_2":
var request = null;
...
}
Alternatively do it just once at the top of your function instead of in each case statement.
A more simplified example if you have a global object:
var xhr = new XMLHttpRequest();
function do_smth(){
xhr.open(...);
}
function do_smth2(){
xhr.open(...);
}
do_smth();
do_smth2();
Instead of a global, you need to make the XHR object scoped properly so each call has a unique XHR.
function do_smth(){
var xhr = new XMLHttpRequest();
xhr.open(...);
}
function do_smth2(){
var xhr = new XMLHttpRequest();
xhr.open(...);
}
I try to make Cross Domain POST requests and get back JSON encoded responses,
everything works fine except in IE 7, 8, 9.
I have try those solutions but i get this error:
Object doesn't support property or method 'setRequestHeader'
Function createXMLHTTPObject() - attempt 1
function createXMLHTTPObject() {
var xmlhttp = false;
var is_IE = window.XDomainRequest ? true : false;
if (is_IE) {
xmlhttp = new window.XDomainRequest();
} else {
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlhttp;
}
Function createXMLHTTPObject() - attempt 2
var XMLHttpFactories = [
function() { return new XMLHttpRequest() },
function() { return new ActiveXObject("Msxml2.XMLHTTP") },
function() { return new ActiveXObject("Msxml3.XMLHTTP") },
function() { return new ActiveXObject("Microsoft.XMLHTTP") }
];
function createXMLHTTPObject() {
var xmlhttp = false;
for (var i=0; i<XMLHttpFactories.length; i++) {
try {
xmlhttp = XMLHttpFactories[i]();
}
catch(e) {
continue;
}
break;
}
return xmlhttp;
}
Function send()
Here it returns the error, at: req.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
function send(postData, callback) {
var url = 'http://domain.com/ajax-processing.php'; //url overlap
var req = createXMLHTTPObject();
if (!req) return;
var method = (postData) ? "POST" : "GET";
req.open(method, url, true);
req.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
if (postData) {
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
}
req.onreadystatechange = function() {
if (req.readyState != 4) return;
if (req.status != 200 && req.status != 304) {
console.log('HTTP error ' + req.status);
return;
}
callback(req);
}
if (req.readyState == 4) return;
req.send(postData);
}
Here i call the send function
var insert = 'id=1&type=insert';
CLib.send(insert, function(data) {
console.log(data);
});
Is it possible to make Cross Domain requests in IE?
How i can leave behind this part, without using any other library like jQuery?
Thanks a lot #Esailija who inform me that i can't make set request headers with the XDomainRequest.
So i tried other methods and solutions also and i finally came back with a simpler method:
changed the POST requests to GET and everything working fine after some small changes.
i have the following code working in all browsers now but IE8.. i read that if i used the xhttp=new ActiveXObject("Microsoft.XMLHTTP"); line it should work for IE but i'm not sure..anyone have experience in getting this to work with ie8
function loadXMLDoc(dname)
{
if (window.XMLHttpRequest)
{
xhttp=new XMLHttpRequest();
}
else
{
xhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.open("GET",dname,false);
xhttp.send();
return xhttp.responseXML;
}
var xmlDoc = loadXMLDoc("nhl_standings_xml.xml");
var x = xmlDoc.getElementsByTagName("nhlall");
Hmm, the code looks okay. Have you tried an Asynchronous request? When you have xhttp.open("GET", dname, false);, it's synchronous. Change that false to a true, and you're asynchronous. Also, you variable xhttp isn't properly declared (correct me if I'm wrong. Being a Python coder, I can't tell half of the time).
Try this code:
function loadXML(url)
{
var xmlHttp;
try
{
// Firefox, Opera 8.0+, Safari
xmlHttp = new XMLHttpRequest();
} catch (e) {
// Internet Explorer
try
{
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
return false;
}
}
}
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
return xmlHttp.responseText;
}
}
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
var xmlDoc = loadXML("nhl_standings_xml.xml");
var x = xmlDoc.getElementsByTagName("nhlall");
i suggest you this MINIMAL ajax engine.
http://pastebin.com/uXJe9hVC
an example of usuage
ajax POST request
Ajax.call('GET','http://localhost/index.php',function(data) {
{
//doing stuff with the data response
},'ASD');
call arguments: URL,callback,POST
this is so easy.
Try this as a request starter:
if (window.XMLHttpRequest) return new window.XMLHttpRequest();
else if (window.ActiveXObject) {
// the many versions of IE's XML fetchers
var AXOs = [
'MSXML2.XMLHTTP.6.0',
'MSXML2.XMLHTTP.5.0',
'MSXML2.XMLHTTP.4.0',
'MSXML2.XMLHTTP.3.0',
'MSXML2.XMLHTTP',
'Microsoft.XMLHTTP',
'MSXML.XMLHTTP'
];
for (var i = 0; i < AXOs.length; i++) {
try { return new ActiveXObject(AXOs[i]); }
catch() { continue; }
}
return null;
}
The order above should be the correct best-to-worse order, BTW.