Read response from HttpRequest in JavaScript - javascript

First, you can ignore that this is sending credentials in an unsafe manner. I'm supposed to handle that after.
My problem is with reading the 'response' or 'responseText' from a HttpRequest to an API. I can see in the console the request is succesful and the response I want is there, but I am not able to retrieve it. I must be missing something basic probably.
This is the response as I can see in the console:
Chrome console
I can see the "web.html" that I want to retrieve and also the status 200. But the console log is empty. This is how I am trying to do this.
const request = new XMLHttpRequest();
request.open('POST', 'https://someurl.net/api/user/login');
const form = document.getElementById('login')
form.addEventListener('submit', callbackFunction);
function callbackFunction(event) {
event.preventDefault();
request.setRequestHeader('Content-Type', 'application/json;charset=UTF-8')
request.send(JSON.stringify(formJson(event)));
console.log(request)
console.log("Status: " + request.status);
console.log("Response: " + request.response);
console.log("ResponseText: " + request.responseText);
};
function formJson(event) {
const credentialsDto = {};
const myFormData = new FormData(event.target);
console.log(myFormData);
myFormData.forEach((value, key) => (credentialsDto[key] = value));
return credentialsDto;
}
For some more details, this is calling my Api in .NET which returns 401 Unauthorized if the credentials are wrong, and 200 OK with a string as in Ok("web.html") if the credentials are correct.
Thank you.
I tried printing the request and trying with all its attributes I could think of. I can see the request is working and the server is sending the response I want, but I am clueless as how to retrieve it properly.
I also tried this thinking that the response might be asynchronous but it didn't work:
while (true)
{
if (request.readyState == 1)
{
console.log("Status: " + request.status);
console.log("Response: " + request.response);
console.log("ResponseText: " + request.responseText);
break;
}
}

The console is empty because the readyState property state 1 merely means that the connection with the server is established.
Furthermore, the XMLHttpRequest object you print to the console is updated immediately when the http-response file is received, which gives the false assumption that it can't be accessed.
This is more or less a boilerplate code-snippet for waiting for the http-response
const request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML =
this.responseText;
}
};
Now let's tailor it with the code you submitted:
const request = new XMLHttpRequest();
const form = document.getElementById('login')
form.addEventListener('submit', callbackFunction);
function callbackFunction(e) {
event.preventDefault();
request.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log("Status: " + request.status);
console.log("Response: " + request.response);
console.log("ResponseText: " + request.responseText);
}
};
request.open('POST', 'https://someurl.net/api/user/login');
request.setRequestHeader('Content-Type', 'application/json;charset=UTF-8')
request.send(JSON.stringify(formJson(e)));
console.log(request)
};
function formJson(e) {
const credentialsDto = {};
const myFormData = new FormData(e.target);
console.log(myFormData);
myFormData.forEach((value, key) => (credentialsDto[key] = value));
return credentialsDto;
}
This should do it. Notice that event is deprecated and that you would continue using e instead.
Instead of depending on the onreadystatechange property, you could also choose for:
request.onload = function(e) {/*Your code*/};
An eventlistener which automatically looks for the succes denoting parameters and is a hack of a lot shorter.
I hope this helps.

Related

Firebase Cloud Function Warning (Function returned undefined, expected Promise or value)

I just set up a cloud function triggered by a sub/pub topic. The function triggers an HTTP-triggered cloud function by, well, making a GET request. It all works well, the only thing that doesn't quite line up is a warning message
Function returned undefined, expected Promise or value
I have to admit I'm not as fluent in promises as I should be, and that might be the reason for the error. Here is the Node code.
exports.triggerClearHidden = functions.runWith(global.runtimeOptions).pubsub.topic('trig').onPublish((message) => {
// const pubsubMessage = message.data;
// console.log(Buffer.from(pubsubMessage, 'base64').toString());
let urlstr = functions.config().rain.projecturl + "/clearHidden";
httpGetAsync(urlstr, (txt => console.log(txt)));
});
function httpGetAsync(theUrl, callback)
{
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200){
return callback(xmlHttp.responseText);
} else {
return callback("the ready state is " + xmlHttp.readyState + " and the status is " + xmlHttp.status);
}
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}

Javascript not including formdata in request

I'm writing an API. I can successfully send data to it in postman by including it in body > form data. However, this code does not send anything as form-data!
addGuild = function () {
req = new XMLHttpRequest();
req.open("GET", "https://gralyn.app/api/server/add/" + window.guild)
formdata = new FormData()
formdata.append('prefix', document.getElementById("install-prefix").value);
req.setRequestHeader("token", this.localStorage.getItem("token"))
req.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
alert("Success!")
} else {
console.log("ERROR: " + this.status)
openModal("error")
}
}
}
req.send(formdata)
}
The API does not receive a prefix as formdata! I am accessing the prefix in flask via request.form['prefix']
Figured it out, javascript wont allow form data in a GET request.

Return WebMethod Response & Use If Statement To Alert User Based On Response

I'm trying to include an if statement that analyzes the webmethod response which is either true or false. I just want to alert the user the post was successful if the response is true or the post was not successful if the response is false.
I can get the response using xhttp.responseText but I can't figure out how to build that into an if statement inside my javascript below:
//JavaScript that Posts to WebMethod
<script>
function createNewComment() {
var xhttp = new XMLHttpRequest();
var url = "http://localhost:57766/PALWebService.asmx/insertComment"
var a = document.getElementsByName("existingguid")[0].value;
var b = document.getElementsByName("newcomment")[0].value;
var c = 'existingguid=' + a + '&newcomment=' + b;
xhttp.open("POST", url, true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
}
};
xhttp.send(c);
}
</script>
I figured it out. After checking that readyState was 4 and status was 200 I simply nested another if statement to check the responseText from the XMLHttpRequest and it was true I called another function and if it was false I notified user the post failed on the webmethod. It may not be perfect, but it works for what I need.
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
if (xhttp.responseText = true) {
addComment(b, today, userName);
}
else {
document.getElementsByName("newcomment")[0].value = '';
$("#commentLabel").html("Your comment was not saved in the database. Please try again or contact system admin.");
}
}
};

Populate table as data chunks are received

I have a problem with my code and I'm struggling finding why it doesn't work as expected.
I have an API that returns data async. and I want the frontend side to add that data as soon as it's being received. What I expect is an API that returns, say 200 items, then javascript to load those 200 items to a table, meanwhile the API keeps returning another 200 items, and then javascript appends them to the table, and so on until there is no more data left.
I'm using vanilla Javascript 5, prototype-based MVC pattern. Perhaps I'm not getting something simple or its far more complex than I expected.
resultView.js
//this function gets executed by some other code not relevant
ResultView.prototype.execute = function(serverName, databaseName, query){
var response = resultController.getData(serverName, databaseName, query);
console.log("response: ", response); //prints undefined
response.done(function(data){ // Uncaught TypeError: Cannot read property 'done' of undefined
console.log("response done: ", response); //doesn't even execute
data.forEach(populateTable); //this code should populates the table
});
}
resultController.js
ResultController.prototype.getData = function(serverName, databaseName, query){
return resultModel.getData(serverName, databaseName, query);
};
resultModel.js
ResultModel.prototype.getData = function (serverName, databaseName, query) {
var dataSend = {
//the code that is being sent
};
var result = "";
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.onprogress = function () {
result += xhr.responseText;
if(xhr.readyState == 4){
console.log("return: ", result); //shows the results properly each time they are received
return result; //not sure about this return
}
}
xhr.send(JSON.stringify(dataSend));
};
}
I know the data is being received in the API, and the data is returned properly in the front end, the issue must be how I am trying to handle it.
Currently, the results I am getting on the console.log at resultModel.js are the expected, the problem seems to be when calling it from resultView.js, I guess when the function calls response.done(), but I am unable to fix it.
Anyone knows how can I approach a solution?
Thanks in advance.
EDIT:
Partially thanks to Ionut, I've managed to make the resultView.js return better datas, but I still have the problem at the resultView.js, when I try to use response.done(...) it tells me it can't do done() of undefined, but the data should be able to be returned. This is my code in resultModel.js now, the rest remains unchanged.
resultModel.js
var xhr = new XMLHttpRequest();
console.log("Sending the request...");
xhr.open("POST", urlBase + "QueryResults", true);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
console.log("return: ", xhr.responseText); //data is logged properly
return xhr.responseText; //it should be returned properly
}
};
xhr.send(JSON.stringify(queryRequest));
You should add a callback function to manage the full response.
If you want to implement something like lazy-loading you should request your API to send you batches of a smaller number of items, you process them then request more until you get them all.
Here is a basic http request.
console.log('Sending the request ...');
var xhr = new XMLHttpRequest();
xhr.open('GET', "//ipinfo.io/json", true);
xhr.send();
xhr.onreadystatechange = processRequest;
function processRequest(e) {
console.log('Getting the response ...');
if (xhr.readyState == 4 && xhr.status == 200) {
var response = JSON.parse(xhr.responseText);
console.log('Your ip address is ' + response.ip);
} else {
console.log('Error state=' + xhr.readyState + ', status=' + xhr.status);
}
}

Using javascript, how to make xhr request to get json of what is in my mongo collection?

I'm trying to make a GET using javascript only (not jQuery, as I am using React) and I'm wondering how to get only the JSON back. Can someone please help? Basically, if I use the postman app and do GET at localhost:3000/api/v1/posts, I am seeing all the posts I have created.
If I can get this into an object, then I can use that later with Object.keys().
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
console.log("success : " + request.responseText);
var mPosts = JSON.parse(request)
} else {
//This would print if something goes wrong along with the error message
console.log("other status : " + request.status + " : " + request.responseText);
}
};
request.open('GET', 'http://localhost:3000/api/v1/posts', true);
request.setRequestHeader('Content-Type', 'application/json');
//need to serialize payload before sending it
request.send();

Categories