XMLHttpRequest contains non-empty response but XMLHttpRequest.response is <emptystring> - javascript

I'm sending HTTP requests and receiving responses with the following code:
var xhr = new XMLHttpRequest()
var waiting = true
var sup = this
var userId = userInfo.userId
var userType = 'student'
if (userInfo.type == 2) {
userType = 'professor'
}
xhr.onreadystatechange = function() {
try {
if (this.status == 200 && waiting) {
waiting = false;
var courses
try {
courses = JSON.parse(xhr.response)
} catch (jerr) {
courses = []
}
sup.courseArray = courses;
console.log(sup.courseArray)
sup.render()
}
} catch (err) {}
}
xhr.open('GET', 'http://localhost:8080/course/read/' + userType + 'Id/' + userId)
xhr.send()
As you can see, I'm only accessing response in the callback, so the server has responded and xhr has been initialized at that point. If I simply call console.log(xhr), I can clearly see response is a non-empty string:
response: "[{\"id\":1,\"professorId\":1,\"name\":\"java\",\"code\":\"CS1017\"}]"
However, if I call console.log(xhr.response), I get
<empty string>
Does anyone know why I'm seeing this discrepancy?

this.status == 200 will be true as soon as xhr.readyState == 2, but the request will not be completely fulfilled until xhr.readyState == 4; at readyState == 2 response will still be empty.
console.log(xhr) will eventually show the status at readyState == 4, but that's 2 readyStates later than when your code tries to access xhr.response.
You have to check that both status == 200 and readyState == 4 are true to be sure a complete response has arrived.

why not try using using JS native fetch instead
var waiting = true
var sup = this
var userId = userInfo.userId
var userType = 'student'
if(userInfo.type == 2) {
userType = 'professor'
}
fetch('http://localhost:8080/course/read/' + userType + 'Id/' + userId)
.then(r => r.json())
.then((response) => {
waiting = false;
sup.courseArray = response;
console.log(sup.courseArray);
sup.render();
})
.catch((e) => {
waiting = false;
console.log(e);
});

Related

JSON.parse Unexpected end of JSON input but the code process correctly the data

I'm using a Cloudflare worker to return a JSON. The code running on the worker is pretty simple
//return JSON
const data = {
pswd: psk_db,
};
json = JSON.stringify(data, null, 2);
}
return new Response(json, {
headers: {
'content-type': 'application/json;charset=UTF-8',
"Access-Control-Allow-Origin": "*",
},
})
Now, for some reason, I correctly recieve the response but when I call the javascript
var parsed = JSON.parse(Http.response);
document.getElementById("json_response_code").textContent = parsed.pswd;
I got
Uncaught SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at RequestCode.Http.onreadystatechange (index.html:83:27)
But I still correctly get the value on parsed.pswd
I can't find the issue as the code works but it throws error anyway
EDIT
Console.log(Http.response) shows
{
"pswd": "nicola"
}
Yes, I'm using it; added code
const Http = new XMLHttpRequest();
const url = my_url;
Http.open("GET", url);
Http.send();
Http.onreadystatechange = (e) => {
console.log(Http.response);
var parsed = JSON.parse(Http.response);
document.getElementById("json_response_code").textContent = parsed.pswd;
};
As suggested by #Jaromanda-X Http.onreadystatechange = (e) was used in the wrong way.
Solution has been
Http.onload = (e) => {
// In local files, status is 0 upon success in Mozilla Firefox
if (Http.readyState === XMLHttpRequest.DONE) {
const status = Http.status;
if (status === 0 || (status >= 200 && status < 400)) {
// The request has been completed successfully
console.log(Http.responseText);
var parsed = JSON.parse(Http.response);
document.getElementById("json_response_code").textContent =
parsed.pswd;
} else {
// Oh no! There has been an error with the request!
console.log(Error);
}
}
};
Http.send();

XMLHttpRequest call is never being made to the server

I have an XMLHttpRequest that appears fine, it doesn't generate any error I can see but I never see the request sent to the server.
Its like its erroring out, or cancelling, even before the call to the server is made. There is no network request in dev tools networking section.
The biggest thing I notice is that although I am setting xhr.timeout = 15000, the timeout in the xhr object states its 0 - but I don't know if this an issue.
Here is my Request, the only thing printing to console in the response processing is the XHR OTHER console message:
function sendError(url,params) {
return new Promise( function(resolve) {
//url - passed from calling function
//params - JSON.stringify({ var1:var1,var2:var2}) ; - passed from calling script
console.log(url) ; // prints proper url to console
console.log(params) ; // prints proper params to console
var xhr = new XMLHttpRequest();
xhr.responseType = 'json' ;
//var params = JSON.stringify({ type:8,subject:sub.value,message:msg.value,emailAddys:toAddresses }) ;
xhr.onreadystatechange = function() {
var status ;
if (xhr.readyState == 15) {
console.log("XHR Tiemout") ;
console.log("Time out ready state = 15") ;
status = {status:false,errMsg:"Time out ready state = 15"} ;
} else if (xhr.readyState == XMLHttpRequest.DONE) {
console.log("XHR Response") ;
console.log(xhr.response) ;
var res = xhr.response[0] ;
if (xhr.status == 200) {
// process API call results
status = {status:true,errMsg:res.message} ;
} else {
status = {status:false,errMsg:res.message} ;
}
} else {
console.log("XHR OTHER") ; <----- this prints to console everytime
console.log(xhr) ;
status = {status:false,errMsg:"Something went wrong, no response from server"} ;
}
resolve(status) ;
}
xhr.open('POST', url, true);
xhr.setRequestHeader('Pragma' , 'no-cache') ;
xhr.setRequestHeader('Expires' , -1) ;
xhr.setRequestHeader('Cache-Control' , 'no-cache,no-store,must-revalidate') ;
xhr.setRequestHeader('Content-Type' , 'application/json') ;
xhr.setRequestHeader('X-Requested-With' , 'com.mydomain') ;
xhr.setRequestHeader('Authorization' , 'Token ' +clientToken) ;
xhr.timeout = 15000 ; // 15 seconds
xhr.ontimeout = function() { console.log("Timed Out!") ; };
xhr.send(params);
}) ;
}
And here is the xhr i am printing to console, there is a sendError in the onreadystatechange() function, but I don't understand the root of the error:

Login using Javascript and REST

I made a REST service, which will return a String "hej" if the log in is true.
I have tested in Java with a rest client and it works fine, but pretty new to javascript and need some help.
I'm using this function
function UserAction() {
console.log(User());
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "http://localhost:8080/Footballmanagerrestservice/webresources/login");
xhttp.setRequestHeader("login", User());
xhttp.responseType = 'text';
xhttp.onreadystatechange = function () {
console.log('DONE', xhttp.readyState);
if (xhttp.readyState == 4) {;
// handle response
var response = xhttp.responseText;
console.log(response);
if (response == "hej") {
var url = "http://localhost:8080/FM3/spil2.jsp";
window.location.href = url;
}
}
};
// send the request *after* the callback is defined
xhttp.send();
return false;
}
function User() {
username = document.getElementById("username").toString();
username = document.getElementById("password").toString();
var UserAndPass = "?username=" + username + "&password=" + password;
return UserAndPass;
}
I show you the client i have i Java, maybe you can see why it's not working.
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
String root="http://localhost:8080/Footballmanagerrestservice/webresources/";
String functionPath="login";
String parameters="?username=s153518&password=holger";
Response res = client.target(root+functionPath+parameters)
.request(MediaType.APPLICATION_JSON).get();
String svar = res.readEntity(String.class);
System.out.println(svar);
}
first part of the code looks ok, the following instead must be handled inside a function because is intrinsically asynchronous
var response = JSON.parse(xhttp.responseText);
console.log(response);
if (response.toString() == "hej") {
var url = "http://localhost:8080/FM3/spil2.jsp";
window.location.href = url
}
return false;
doc: https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/onreadystatechange
essentially you're trying to handle the response as a syncrhonous call, but it's not, the response it's not immediatly avaiable, for this reason you have to register a callback (from the doc must be attached to the field onreadystatechange) that will be triggered by javascript as soon as the server response is available.
try to change it like so:
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
// handle response
var response = JSON.parse(xhttp.responseText);
console.log(response);
if (response.toString() == "hej") {
var url = "http://localhost:8080/FM3/spil2.jsp";
window.location.href = url
}
}
}
xhr.send();

foreach only sends last xhr request

I have a textarea where users can enter multiple URLs which in return will be used for an API request.
The issue I run into is that only the last URLs API request gets captured (sometimes multiple times).
$('.start').on('click',function()
{
var url_list = $("#url-list").val();
var urls = url_list.split("\n");
for (var i = 0, len = urls.length; i < len; i++) {
console.log("i is "+i)
var xhr = new XMLHttpRequest();
xhr.open('GET', urls[i], true);
xhr.send();
xhr.onreadystatechange = processRequest;
// send API request
function processRequest() {
if (xhr.readyState == 4 && xhr.status == 200) {
var response = JSON.parse(xhr.responseText);
console.log(response);
}
}
}
});
I don't see exactly where I am doing something wrong, I might be blind to it or just don't know any better. Any help would be appreciated. PS. fairly new to making API requests.
Welcome to closures.
The problems here are:
The loop could be finished before the first request starts, so it takes the last url in the array
In the callback you are referencing the same xhr object
You can try one of the different solutions here.
Replacing xhr with this in the callback is the fastest fix:
function processRequest() {
if (this.readyState == 4 && this.status == 200) {
var response = JSON.parse(this.responseText);
console.log(response);
}
}
See this fiddle for a running example.
You could update your code like this
var requestIndex = 0;
var urls = [];
$('.start').on('click',function()
{
// Reset request index
requestIndex = 0;
var url_list = $("#url-list").val();
urls = url_list.split("\n");
// Send Http request
sendRequest(urls, requestIndex);
});
// Send Http request
function sendRequest(urls, index) {
// Send API request
var xhr = new XMLHttpRequest();
xhr.open('GET', urls[index], true);
xhr.onreadystatechange = processRequest;
xhr.send();
}
// Process API request
function processRequest(e) {
if (e.target.readyState == 4 && e.target.status == 200) {
var response = JSON.parse(e.target.responseText);
console.log(response);
}
requestIndex++;
if (requestIndex < urls.length) {
sendRequest(urls, requestIndex);
}
}

Overriding a variable within another function JS

Is it possible for me to call a function then override the contents of the variable before actually running it?
So I have a function that basically pulls in my Git profile like this:
var GetGitInfo = function() {
var xhr = new XMLHttpRequest();
var gitURL = "https://api.github.com/users/myself/repos";
xhr.open("GET", gitURL);
xhr.send(null);
xhr.onreadystatechange = function() {
var DONE = 4; // readyState 4 means the request is done.
var OK = 200; // status 200 is a successful return.
if (xhr.readyState === DONE) {
if (xhr.status === OK) {
// console.log(xhr.responseText);
console.log(JSON.parse(xhr.responseText));
} else {
console.log('Error: ' + xhr.status);
}
}
};
}
Then I call the function in another step by doing GetGitInfo(); which all works fine.
However, If I wanted to call the function and replace the gitURL variable how would I achieve that?
So something like
GetGitInfo(
gotURL= "https://api.github.com/users/new_user/repo";
);
You can't modify a local variable to a function from outside the function. They are private to the function's implementation.
But, since it's your own function, you can just create an argument that can be passed into the function. You can even make the argument optional so it will take your initial value as the default value if it is not passed.
var GetGitInfo = function(url) {
var xhr = new XMLHttpRequest();
var gitURL = url || "https://api.github.com/users/myself/repos";
xhr.open("GET", gitURL);
xhr.send(null);
xhr.onreadystatechange = function() {
var DONE = 4; // readyState 4 means the request is done.
var OK = 200; // status 200 is a successful return.
if (xhr.readyState === DONE) {
if (xhr.status === OK) {
// console.log(xhr.responseText);
console.log(JSON.parse(xhr.responseText));
} else {
console.log('Error: ' + xhr.status);
}
}
};
}
Then, you can use the function the way you were using it or you can pass in an URL to use:
getGitInfo(); // uses your default URL
getGitInfo("http://someURL"); // uses the URL you pass in
FYI, this function looks like it will ultimately need to either return a promise or accept a callback so you can communicate the results back to the caller.
From the snippet above you need to set the url as a function parameter so when calling it uses the specified url.
var GetInfo = function(url) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send(null);
xhr.onreadystatechange = function() {
var DONE = 4; // readyState 4 means the request is done.
var OK = 200; // status 200 is a successful return.
if (xhr.readyState === DONE) {
if (xhr.status === OK) {
// console.log(xhr.responseText);
console.log(JSON.parse(xhr.responseText));
} else {
console.log('Error: ' + xhr.status);
}
}
};
GetInfo("https://api.github.com/users/myself/repos");
You should do a toString() on the function:
GetGitInfo.toString()
Then you should do a text search and replace on the variable and it's data:
GetGitInfo.toString().substring(0,GetGitInfo.indexOf('somestring'))+'gitUrl="newURL"'+GetGitInfo.toString().substring(.......)
Then you should eval that string!
Or, you know, use function parameters. Either way. Whatever's easiest.
Pass a parameter to the function:
var GetGitInfo = function(gitURL) {
var xhr = new XMLHttpRequest();
xhr.open("GET", gitURL);
xhr.send(null);
xhr.onreadystatechange = function() {
var DONE = 4; // readyState 4 means the request is done.
var OK = 200; // status 200 is a successful return.
if (xhr.readyState === DONE) {
if (xhr.status === OK) {
// console.log(xhr.responseText);
console.log(JSON.parse(xhr.responseText));
} else {
console.log('Error: ' + xhr.status);
}
}
};
}
GetGetInfo("https://api.github.com/users/myself/repos");
Just add a parameter to your function:
var GetGitInfo = function(gitURL) {
var xhr = new XMLHttpRequest();
xhr.open("GET", gitURL);
xhr.send(null);
xhr.onreadystatechange = function() {
var DONE = 4; // readyState 4 means the request is done.
var OK = 200; // status 200 is a successful return.
if (xhr.readyState === DONE) {
if (xhr.status === OK) {
// console.log(xhr.responseText);
console.log(JSON.parse(xhr.responseText));
} else {
console.log('Error: ' + xhr.status);
}
}
};
}
and call it like this:
GetGitInfo("https://api.github.com/users/myself/repos");
Use the parameters
var getData = function(url){
// url can be used here
}
var data = getData("http://apiurl.xy")

Categories

Resources