Synchronous XMLHttpRequest on the main thread is deprecated within embedded Javascript code - javascript

I have scripted a simple Ajax function and embedded this to my website.
On the console I get this warning
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.
What does this mean and how to avoid it?
function readTextFile(file) {
var rawFile = new XMLHttpRequest();
var allText = "";
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function () {
if (rawFile.readyState === 4) {
if (rawFile.status === 200 || rawFile.status == 0) {
allText = rawFile.responseText;
}
}
}
rawFile.send(null);
return allText;
}
function load() {
var allText = readTextFile('drinks.json');
var mydata = JSON.parse(allText);
var div = document.getElementById('cocktaillist');
div.innerHTML = "";
for (var i = 0; i < mydata.length; i++) {
div.innerHTML = div.innerHTML + "<p class='inner' id="+i+">"+ mydata[i].name +"</p>" + "<br>";
}
}

You need to change your code to use asynchronous Ajax requests. As the warning indicates, using synchronous requests is bad for the user experience. Also, there literally never is a reason to use synchronous Ajax requests, ever.
And that means you need to use callback functions. Compare:
function getText(path, success) {
var req = new XMLHttpRequest();
req.open("GET", path, true);
req.onreadystatechange = function () {
if (req.readyState === 4) {
if (req.status === 200) {
success(req.responseText); // call a function with the received value
} else {
console.log("unexpected response status " + req.status);
}
}
};
req.send(null);
}
function load() {
getText('drinks.json', function (allText) { // pass a function to call when the request is done
var mydata = JSON.parse(allText);
var div = document.getElementById('cocktaillist');
div.innerHTML = "";
for (var i = 0; i < mydata.length; i++) {
div.innerHTML = div.innerHTML + "<p class='inner' id="+i+">"+ mydata[i].name +"</p>" + "<br>";
}
});
}

The message you observed:
Synchronous XMLHttpRequest on the main thread is deprecated because of
its detrimental effects to the end user's experience.
Is a warning about the fact that a synchronous request defeats the asynchronous nature of JavaScript and blocks the user interface, which causes bad user experience, especially in case of bad network quality.
You should set true as third parameter of rawFile.open() and you already provided a rawFile.onreadystatechange callback in order to execute code when you have received a response, so the rest of your code is fine.

Related

XMLHttpRequest send one after another

How do I send these XMLHttpRequests one at a time? Right now they are all firing immediately and if there are over six it locks up the server.
for (var i = 0; i <= document.getElementsByName("combobox")[0].value; i++) {
(function (i) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/grabdatafromeanotherpage.aspx", true);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
document.getElementById("txtHint").innerHTML = document.getElementById("txtHint").innerHTML + xhr.responseText;
}
}
})(0);
}
Just some untested ideas that may make Javascript gurus scream in agony, but hey, they haven't answered:
You could probably get it to work with (deprecated) synchronous calls, doing something like this:
for (var i = 0; i <= document.getElementsByName("combobox")[0].value; i++) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/grabdatafromeanotherpage.aspx", false);
xhr.send(); // This will block until a request has been received, no need for a callback function
if (xhr.status == 200) {
document.getElementById("txtHint").innerHTML = document.getElementById("txtHint").innerHTML + xhr.responseText;
}
}
If you don't want to use synchronous calls, and you are sure the problem is on the server side (ie. the server can't handle this many almost-simultaneous requests) you could call request number i+1 from the callback of request i, but it would be very messy code.
You could also use the setTimeout() function to send the requests at intervals the server can handle, 500ms in this example:
for (var i = 0; i <= document.getElementsByName("combobox")[0].value; i++) {
setTimeout(myXHR, 500 * i)
}
function myXHR() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/grabdatafromeanotherpage.aspx", true);
xhr.onreadystatechange = function () {
if (xhr.status == 200 && xhr.readyState == 4) {
document.getElementById("txtHint").innerHTML = document.getElementById("txtHint").innerHTML + xhr.responseText;
}
};
xhr.send();
}
but the order of arrival of the responses would not be guaranteed.
There are probably better/hipper/more modern ways of doing all this with fetch/await.
If you have full control over the server, I would first try to persuade it somehow to accept and process the quick, successive requests; I find it a bit odd the server can't handle this.

Trying to post to a .txt file fails but performing a get does work

My partner and I are trying to get a domain that I own, communicate with a ios app that is run on objective c to work via http. He is using the code that was provided by this link Sending an HTTP POST request on iOS.
He is able to do a GET to receive the data in my .txt page but when he performs a PUT to try and write to that file so that I can get that data it fails. We are both rather new to http so it is possible that we are missing something. A concern we have is that he doesn't have the privileges to write to this file. Any advice would help, thanks!
Here is the javascript I am using on my side. I added a header to my response to try and resolve the cors issue.
(function () {
window.onload = function () {
httpGetAsync("http://students.washington.edu/bharatis/distances.txt", processData)
//alert("hello inside onload");
document.getElementById("first").innerHTML = leader1;
document.getElementById("second").innerHTML = leader1;
document.getElementById("third").innerHTML = leader1;
//window.onbeforeunload = update;
}
function processData(responseText) {
//alert(responseText);
var txt = "";
var x = responseText.getElementsByTagName('Distance'); // Talk to alex about
for(i = 0; i < x.length; i++) {
txt += x[i].childNodes[0].nodeValue;
}
var result = parseDouble(txt);
alert(result);
}
function httpGetAsync(theUrl, callback) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
callback(xmlHttp.responseText);
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.setRequestHeader("Access-Control-Allow-Origin", "*");
xmlHttp.send("response message");
}
})();

Accessing an array from with an AJAX callback function

I'm trying to use an AJAX call to update a bunch of image elements on a page. The list of elements to update is held in an array and the URLs to assign to each image are retrieved from a PHP page via AJAX.
The code I have below doesn't work because imagesArray[i] is undefined when it is called from the callback function in the AJAX call - due to the asynchronous nature of JavaScript presumably.
var imagesArray = document.getElementsByClassName('swappableImages');
for (i = 0; i < imagesArray.length; i++) {
var requestUrl = "http://example.com/getAnImageURL.php";
getDataViaAJAX(requestUrl, function(data) {
alert('img url=' + data.responseText);
imagesArray[i].src = data.responseText;
});
}
function getDataViaAJAX(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
On reading around it seems that one way to solve this would be to use a closure, however closures are something I've still not managed to get my head around and the examples I have found have just confused me further.
So, how can I update each element in the array as an when the AJAX function returns?
Note that the 'duplicate' question that has been identified is a jQuery version of the question with jQuery specific answers. I am using vanilla JavaScript.
Note: First example/approach - referred to in comments - removed from answer.
You may try this:
var requestUrl = "http://example.com/getAnImageURL.php";
for (i = 0; i < imagesArray.length; i++) {
(function(j) {
getDataViaAJAX(requestUrl, function(data) {
alert('img url=' + data.responseText);
imagesArray[j].src = data.responseText;
});
})(i);
}

XMLHttpRequest() javascript

to resume my problem, i'm using many XMLHttpRequest() rockets, with a view to get the value (miniTable) returned by the TableRow() function. The problem is, with the alert() on the end of the TableRow() function, i'm have exactly the value that i want, but on TableContent2 variable i'm having an "Undefined" value. I don't know why!! here all the JS file that i'am using (don't care about variables and code calculating the variables). I really need your help, because i'm blocked since 3 days on that. Thank you again and good afternoon freinds.
(function() {
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
myFunction(xmlhttp);
}
};
xmlhttp.open("GET", "File1.xml", true);
xmlhttp.send();
})();
function ContentFunction(func) {
TableContent2 = TableRow();
alert(TableContent2);
}
function TableRow() {
xmlhttp3 = new XMLHttpRequest();
xmlhttp3.onreadystatechange = function() {
if (xmlhttp3.readyState == 4 && xmlhttp3.status == 200) {
texttest = myFunction2(xmlhttp3);
alert(miniTable);
return miniTable;
}
};
xmlhttp3.open("GET", "File2.xml", true);
xmlhttp3.send();
}
function myFunction2(xml) {
var xmlDoc2 = xml.responseXML;
var ObjectText;
var x = xmlDoc2.getElementsByTagName("Clip");
/*Calcule de ObjectText*/
alert(ObjectText);
return ObjectText;
}
function myFunction(xml) {
xmlhttp2 = new XMLHttpRequest();
var xmlDoc = xml.responseXML;
var x = xmlDoc.getElementsByTagName("Film");
xmlhttp2.onreadystatechange = function() {
if (xmlhttp2.readyState == 4 && xmlhttp2.status == 200) {
myFunction2(xmlhttp2);
}
};
xmlhttp2.open("GET", "File2.xml", true);
xmlhttp2.send();
}
TableRow returns nothing. The return statement at xmlhttp3.onreadystatechange isn't in the earlier scope. Besides that, your xmlhttp3 is set to be asynchronous, then you can't directly return any information of the AJAX. Synchronous requests, which are deprecated (that's why you shouldn't use them), can be directly read, since they act like a infinite loop that breaks when the request is done (for(;xhr.readyState!==4;);, doing this manually will pause the request and the script execution forever, this is why synchronous requests have been made before.).
Synchronous requests aren't a good idea, they break interaction with entire of the page, since they pause the page/script execution. For instance, if you've a animation, it'll be paused, including event listeners.
Also, it looks like miniTable haven't been declared in any part of your code.
Consider using callback functions, they'll be stored in the TableRow scope and can be called later, with extra arguments.
This is a base:
function ContentFunction(func) {
TableRow(function(TableContent2) {
alert(TableContent2);
});
}
function TableRow(doneFnc) {
var xmlhttp3 = new XMLHttpRequest;
xmlhttp3.onreadystatechange = function() {
if (xmlhttp3.readyState === 4 && xmlhttp3.status === 200) {
var texttest = myFunction2(xmlhttp3);
/* success callback */
doneFnc(texttest);
}
};
xmlhttp3.open("GET", "File2.xml", true);
xmlhttp3.send();
}

Load ~ 400 (Bad Request). XmlHttpRequest works on local, but not on server-side

I am working on async load (using XMLHttpRequest .readystate & .responseText) of product table contents on pagination or filter changing. Funtions I wrote work perfectly but on local only. On apache/ngnix server-side it returns bad request. Please help.
function loadContent(link) {
var http = createRequestObject();
if( http ) {
http.open('load', link);
http.onreadystatechange = function () {
if(http.readyState == 4) {
var div = document.createElement('div');
div.innerHTML = http.responseText;
var all = div.getElementsByTagName('div');
for (var i = 0, len = all.length; i < len; i++) {
if (all[i] && all[i].getAttribute('id') == 'to-ajax') {
var deep = all[i].getElementsByClassName('product-layout col-lg-4');
$('.load').before(deep);
}
}
}
}
http.send(null);
} else {
document.location = link;
}
}
function createRequestObject() {
try { return new XMLHttpRequest() }
catch(e) {
try { return new ActiveXObject('Msxml2.XMLHTTP') }
catch(e) {
try { return new ActiveXObject('Microsoft.XMLHTTP') }
catch(e) { return null; }
}
}
}
Error warning refers to this line of code ~ } http.send(null);
It seems that problem is on .onreadystatechange function, but have no idea how to test it to define what an exact issue is.
The first argument to open needs to be a string containing an HTTP request method. "load" is not an HTTP request method. Examples include "GET" and "POST". The invalid HTTP is likely causing your server to respond with the Bad Request error.

Categories

Resources