Why does XMLHttpRequest return two values? - javascript

I am trying to alert a txt file from my webserver in JavaScript.
This is what I have:
var client = new XMLHttpRequest();
client.open('GET', 'example.com/maers.txt');
client.onreadystatechange = function() {
var maers = client.responseText
alert(maers)
}
client.send();
The problem is that there are two alerts:
The first alert returns an empty string.
The second alert returns the actual value.
I am trying to make the alert return only the needed value.

You have to check if the state actually is READY. Add to following to your callback:
if(client.readyState === XMLHttpRequest.DONE && client.status === 200) { }

Related

Setting 'None' instead of required data

I want to set a field value based on the value of another field(Using AJAX). Here, I am trying to set the same value but it is getting set to 'None' instead of the actual value.
script for sending a request :
<script>
function getCustomerName() {
var x = document.ipwhitelistindex.AWSID.value;
console.log(x)
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.ipwhitelistindex.CUSTNAME.value = this.responseText;
}
};
xhttp.open('POST', 'getcustomernamefromexcel', true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send(x);
}
</script>
Here, I am sending x. I can see the exact value in the console but it is setting to None on the page.
python :
def getcustomernamefromexcel(request):
value = request.POST.get('x')
return HttpResponse(value)
If you call xhttp.send(x), then the name of the variable is no longer known. You need to encode this, for example with:
xhttp.send("x="+encodeURIComponent(x));

Unable to get the same results with 2 pieces of somewhat similar XMLHttpRequest

Hope you are able to help or just help me understand why I have 2 almost similar codeblocks where one does not do what I expect.
I am trying to make some API calls where I populate a variable with the data that is pulled from the API call. In the first there is no problem at all, but the second I can't populate the variable.
I have tried googling the problem and it seems to be because of the asynchronous nature of XmlHttprequests. But again, I do not get why one solutions works and another don't.
The solution that work:
// Get JSON and convert it to an object
var obj;
const Http = new XMLHttpRequest();
const url = "https://type.fit/api/quotes";
Http.open("GET", url);
Http.send();
Http.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
obj = JSON.parse(Http.responseText);
}
};
In this solution I am able to get the data and populate the variable obj and use it globally.
link to the solution: https://codepen.io/Kfriis/pen/QWjGZmx
The solution that don't work:
//function that takes a currency in capital letters and returns
var rates;
var currency = 'gbp';
const currencyString = currency.toUpperCase();
const API = "api.frankfurter.app"
const URL = `https://${API}/latest?amount=1&from=${currencyString}&to=DKK`
const http = new XMLHttpRequest();
http.open("GET", URL);
http.send();
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
rates = JSON.parse(http.responseText);
}
};
console.log(rates)
This do, for some reason, not work. I do not get why the rates variable do not get populated since the request is basically the same for the first code snippet.
I have come down to an idea of it being because the data sent from the 2 API endpoints may be different in some way. Because if it was only because of the asynchronous requests, both code snippets should return undefined.
Link https://codepen.io/Kfriis/pen/VwvpKmd
I do hope someone is able to shine some light on this.
I must be doing something wrong in the second snippet, because I can console.log() from inside the onreadystatechange but not outside it. Which led me to believe for a long time that it was a scoping issue.
Your code does work. However, you're logging console.log(rates) outside the http.onreadystatechange-function which means you're logging the rates before you get the response. If you change the code block
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
rates = JSON.parse(http.responseText);
}
};
console.log(rates)
to
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
rates = JSON.parse(http.responseText);
console.log(rates)
}
};
it should work.
Here's a working example code if you wanna add the code to a function.
// Function that takes a currency in capital letters and returns
function getCurrencyRates(currency, cb) {
const currencyString = currency.toUpperCase();
const API = "api.frankfurter.app"
const URL = `https://${API}/latest?amount=1&from=${currencyString}&to=DKK`
const http = new XMLHttpRequest();
http.open("GET", URL);
http.send();
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
cb(JSON.parse(http.responseText));
}
};
}
// Call the function and pass "gbp" as currency.
// Rates will be logged in response.
getCurrencyRates('gbp', function(response) {
console.log(response);
});

assign variable to ajax responseText [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I'm trying to load the text content of a file into a variable using ajax.
The function readFile() seems to works fine. I think the issue is that my file, 'countries.csv' is big and taking too long to load, so console.log(x) just returns 'undefined'
// last argument in open() is async; must be true or else chrome gives an error
function readFile(file) {
var xhr = new XMLHttpRequest();
xhr.open('GET', file, true);
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && xhr.status === 200) {
var fileContent = xhr.responseText;
// console.log(fileContent); <-- this line would work just fine
return fileContent;
}
}
xhr.send(null);
}
// so this next line takes some time to run
var x = readFile('/data/countries.csv');
// and this line runs before the last line is done
console.log(x);
What can I do to load the content of the file 'countries.csv' into the variable x before I start actually working with the variable x?
Am I missing some kind of event listener?
You need to pass a callback :)
Try
function readFile(file, cb) {
var xhr = new XMLHttpRequest();
xhr.open('GET', file, true);
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && xhr.status === 200) {
var fileContent = xhr.responseText;
return cb(fileContent);
}
}
xhr.send(null);
}
readFile('/data/countries.csv', thing => console.log(thing));
Here's some extra stuff to learn more about callback/async programming in javascript: http://www.learn-js.org/en/Callbacks

Remove a line from JSON parse

I am working with JIVE JSON RESTFul API and on their API they have a security
(I am referring to the throw 'allowIllegalResourceCall is false.'; )
throw 'allowIllegalResourceCall is false.';
{
"id" : "52104",
}
I am using this code to try to PARSE IT:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
document.getElementById("topdisplay").innerHTML = myObj.id;
}
};
xmlhttp.open("GET", "http://mysite/API/",true);
xmlhttp.send();
And I am getting an error because of that starting line.
I looked everywhere to try finding a solution to skip that to the JSON PARSE would work but I can't seem to find a way that works to do it.
Also I know that the parsing code works because when I remove the first line it works perfectly.
Any help?
JIVE REST API introduced this to help prevent against JSON Hijacking back when web browsers were susceptible.
You'll need to first find {, and do a substring from that position to the end of the string.
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var response = this.responseText
var myObj = JSON.parse(this.responseText.substring(this.response.indexOf('{')));
document.getElementById("topdisplay").innerHTML = myObj.id;
}
};
xmlhttp.open("GET", "http://mysite/API/",true);
xmlhttp.send();
NOTE:
using RegEx, you'll need to find the first line with throw and ending in a semi-colon, if found replace with an empty string.
JSON.parse(response.replace(/throw.*;/, "").trim());

Unable to return an object's value from a JavaScript function

I have a function which attempts to capture a return value from a calling function in the following manner:
var select = xhrRetrieve(projID);
Here is an example of the xhrRetrieve function:
function xhrRetrieve(projID) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
if(xhr.status == 200) {
var obj = $.parseJSON(xhr.responseText);
return obj.select.toString();
}
}
}
var url = "ajax.cgi";
var data = "action=retrieve-opp&proj-id=" + projID;
xhr.open("POST",url);
xhr.setRequestHeader("Content-Type","application/x-www-urlencoded");
xhr.send(data);
}
I am using jQuery in conjunction with straight JavaScript. Whenever I attempt to get the value of obj.select using:
var select = xhrRetrieve(projID);
Select always comes back undefined.
What am I doing wrong?
The function doesn't return anything
The moment you call your function, the (not currently present) return value is being assigned to select. At the same moment, your ajax request is being fired, which takes time to complete; the callback function will not be called until the ajax request has completed (and succeeded).
This should work:
function doStuffWithTheAjaxResponse(select) {
// do stuff
}
function xhrRetrieve(projID) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
if(xhr.status == 200) {
var obj = $.parseJSON(xhr.responseText);
doStuffWithTheAjaxResponse(obj.select.toString());
}
}
}
var url = "ajax.cgi";
var data = "action=retrieve-opp&proj-id=" + projID;
xhr.open("POST",url);
xhr.setRequestHeader("Content-Type","application/x-www-urlencoded");
xhr.send(data);
}
Since the request is asynchronous the function will return before your code in onreadestatechange fires. You can switch to synchronous and get the value before the function returns:
function xhrRetrieve(projID) {
var returnVal;
var xhr = new XMLHttpRequest();
var url = "ajax.cgi";
var data = "action=retrieve-opp&proj-id=" + projID;
//3rd param is false to switch to synchronous
xhr.open("POST",url, false);
xhr.setRequestHeader("Content-Type","application/x-www-urlencoded");
xhr.send(data);
if(xhr.readyState == 4) {
if(xhr.status == 200) {
var obj = $.parseJSON(xhr.responseText);
return obj.select.toString();
}
}
}
The function xhrRetrieve doesn't have a return value. What do you expect to happen?
You have two functions there. The inner function returns a value, but not the outer one. The inner function is an event handler so the return value doesn't go anywhere. Your XMLHttpRequest is asynchronous, so you won't get a return value right away. See this post for a more detailed explanation: parameter "true" in xmlHttpRequest .open() method

Categories

Resources