This question already has answers here:
How to get the response of XMLHttpRequest?
(4 answers)
Closed 6 years ago.
I'm trying to get a Java Servlet to send some HTML as a response to a request from a JavaScript function. However, while the servlet function is getting called and seems to be sending a response, the Javascript functions is getting nothing but an empty String.
Here is the Servlet method:
String type = request.getParameter("type");
if(type.equals("locos")) {
response.setContentType("text/html");
//this prints out
System.out.println("Responding with vehicle list");
//deal with response
PrintWriter out = response.getWriter();
out.write("<p>test response</p>"); //finish
}
Here is the JavaScript function:
this.updateVehicleList = function () {
var type = "locos";
var xhr = new XMLHttpRequest();
xhr.open('GET', 'GetList?type=' + encodeURIComponent(type),true);
xhr.send(null);
//deal with response
var res = xhr.responseText;
//for testing
if (res == "") {
window.alert("I'm getting nothing");
}
view.showVehicleList(res);
};
The "I'm getting nothing" message outputs every time. How do I get the JavaScript to actually receive the response from the Servlet?
You are making an asynchronous request and so the response is not immediately available. You are trying to get the responseText before the response has even been received.
Use the onreadystatechange event:
...
...
xhr.send(null);
xhr.onreadystatechange = function () {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200){
//deal with response
var res = xhr.responseText;
//for testing
if (res == "") {
window.alert("I'm getting nothing");
}
view.showVehicleList(res);
}
};
If you are intending to make a synchronous request, then set the third argument to false and your original code will work.
xhr.open('GET', 'GetList?type=' + encodeURIComponent(type),false);
// ^^^^^
Related
I am very new to JS, trying to create simple page which does next:
takes IP of some server
then sends a get request to this server
parses get response,
adds filtered lines to the table on html page.
I was able to do all the steps through the browser console but when, moving to the JS file with get function for some reason function does not return value.
In below code snip line 6 will print undefined in the console.
Any idea how to return "statuses" from the function getStatus?
Should it be some timeout between line 5 and 6?
Thanks!
$("input[type='text']").keypress(function(event){
if(event.which === 13){
var address = $(this).val();
var urlStat = 'http://'+address+':666/bla?open=stats';
var status = getStatus(urlStat);
console.log(status);
$("input[type='text']").val('');
$('table').append("<tr><th>"+address+"</th><th><ul></ul></th><th></th></tr>");
}
});
function getStatus(url){
var xhr = new XMLHttpRequest;
xhr.open("GET", url);
xhr.send();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var regexStatus = /(\w+ state:.*?)</g
var response = xhr.responseText;
var statuses = response.match(regexStatus);
console.log('Inside function getStatus'+statuses);
return statuses;
};
}
};
The problem with your code is that the status is returned after your your request has been sent. That gives a small delay. Because you immediatly ask for the return value of getStatus, you will get undefined.
You could solve this problem with a callback function:
function getStatus(url,callback){
var xhr = new XMLHttpRequest;
xhr.open("GET", url);
xhr.send();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var regexStatus = /(\w+ state:.*?)</g
var response = xhr.responseText;
var statuses = response.match(regexStatus);
console.log('Inside function getStatus'+statuses);
if(callback) callback(statuses);
};
}
};
You call the getStatus function with a function, which is called after you got a response from you request.
E.g:
getStatus(url,function(statuses){
console.log(statuses);
});
EDIT
For a better and longer explanation, consider to check out How do I return the response from an asynchronous call?
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.");
}
}
};
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);
}
}
I am trying to accomplish simple yet seems complicated task. I am trying to make AJAX call from pure JavaScript (front end) to aspx page (back end) without including any asp ajax library aiming no asp page rendering on front end i.e. only html+JS for front end.
So here is how it goes, on the front end this js code will send asynchronous call to asp page with a variable. The variable is derived from text box value.
function handleRequest() {
if (xhr.readyState < 4) {
return; // The response is not available yet , we do nothing
}
if (xhr.status !== 200) {
alert('Error!'); // error HTTP
return;
}
}
function getValue() {
var textVal = document.getElementById("test1").value;
xhr.open('GET', 'WebForm1.aspx?q=' + textVal , true);
xhr.send();
var response = xhr.responseText;
document.getElementById("bdy").innerHTML = response;
}
var btn = document.querySelector("button");
var xhr = new XMLHttpRequest();
var body = document.getElementById("bdy");
xhr.onreadystatechange = handleRequest;
document.getElementById("header").innerHTML = Date();
btn.addEventListener('click', getValue, true);
Now, on the back end asp code which will echo the textbox value with the time stamp from the server.
protected void Page_Load(object sender, EventArgs e)
{
string getRequest = Request.QueryString["q"];
DateTime dt = DateTime.Now;
string responseText = getRequest + dt.ToString();
Response.Write(responseText);
}
Finally, this code works perfect when I make synchronous call i.e.
xhr.open('GET', 'WebForm1.aspx?q=' + temp, false); but fails if I send asynchronous call i.e. xhr.open('GET', 'WebForm1.aspx?q=' + temp, true);
I would really appreciate your help.
Code that uses data obtained by asynchronous operations should be placed in a callback invoked after the data arrives. You already have such callback function - handleRequest:
function handleRequest() {
if (xhr.readyState < 4) {
return; // The response is not available yet , we do nothing
}
if (xhr.status !== 200) {
alert('Error!'); // error HTTP
return;
}
var response = xhr.responseText;
document.getElementById("bdy").innerHTML = response;
}
function getValue() {
var textVal = document.getElementById("test1").value;
xhr.open('GET', 'WebForm1.aspx?q=' + textVal , true);
xhr.send();
}
I found the answer. The problem was that when doing the AJAX synchronous call, the browser would wait for the response from the server before storing the result to the variable response and hence display the results. However, when doing asynchronous call, the browser won't wait for the response and hence response variable will be null and the innerHTML will display nathing.
By adding a delay to the response receiving code line, the code works perfectly. Here is the code.
setTimeout(function () {
var response = xhr.response;
document.getElementById("bdy").innerHTML = response;
}, 50);
Thanks
I'm using a Javascript to ask our app (which is in Google App Engine) if the file a user wants to upload is already in his list of files (he will overwrite).
I know how to send the request, but how can I create a response from the server, using Python?
This is the request:
var req = new XMLHttpRequest();
req.open('POST', 'https://safeshareapp.appspot.com/upload', async);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.setRequestHeader("Content-length", body.length);
req.setRequestHeader("Connection", "close");
if (async) {
req.onreadystatechange = function() {
if(req.readyState == 4 && req.status == 200) {
var response = null;
try {
response = JSON.parse(req.responseText);
} catch (e) {
response = req.responseText;
}
callback(response);
}
}
}
// Make the actual request
req.send(body);
As you see, we are getting the responseText from the request after everything has gone OK, but my question is how do we fill that responseText field on the server side??
class MyRequestHandler(webapp.RequestHandler):
def get(self):
import json
result = {"filename": xxx} // just an example, result can be any Python object
json_obj = json.dumps(result)
self.response.out.write(str(json_obj))