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?
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I've got two functions in Javascript. One gets JSON data from a php file.
{"company_name":"","job_title":"Superhero","unix_time_convert":"Posted 06th of September '18","link":"2"}
The javascript function to return the JSON is this:
function assignJsonData() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var data = (this.response);
return data;
//alert( data );
}
};
xmlhttp.open("GET", 'test_echo.php?row=1', true);
xmlhttp.send();
}
Notice that alert( data ); will return the JSON data in a box.
But when I assign the function to a variable elsewhere like so, it returns undefined.
window.onload = function () {
var data = assignJsonData();
alert(data);
}
What am I missing here?
Sorry to ask, I've been on this for hours...
Thanks
Andy
You should use callBack to retrieve data from ajax request , and get data when ajax request is finieshed , your could should look like :
function assignJsonData(callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
callback(this.response);
}
};
xmlhttp.open("GET", 'test_echo.php?row=1', true);
xmlhttp.send();
}
window.onload = function () {
assignJsonData(function(data){
alert(data);
});
}
As Jafar pointed, you should use a callback!
If you want to check the order the things is executed, run the code bellow.
var returnData = "";
function assignJsonData() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
console.log(this.readyState, this.status);
if (this.readyState == 4 && this.status == 200) {
returnData = this.response;
console.log('enter');
//console.log(this.response);
//return data;
//alert( data );
}
};
xmlhttp.open("GET", 'https://jsonplaceholder.typicode.com/todos/1', true);
xmlhttp.send();
}
assignJsonData();
console.log("returnData: " + returnData);
XMLHttpRequest is asynchronous. You need to either use a callback or a Promise.
function assignJsonData(callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var data = this.response
callback(data)
}
};
xmlhttp.open("GET", 'test_echo.php?row=1', true);
xmlhttp.send();
}
window.onload = function () {
assignJsonData(function(data) {
alert(data)
});
}
You need to use Promise.
Check - How do I promisify native XHR?
You don't have the data in alert, because the response is not ready I guess.
I hope someone can help me, because i can't get it to work and it's really frustrating.
I have the following code
var getJSON = (url, callback) => {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
callback(xhr.response);
}
};
xhr.send();
};
I want to use it to get a json object from the given url but inside the function I want to use the response to get another json object back.
var func1 = (url) => {
getJSON(url, (data) => {
//Do smth here with the data and then for example
func2('https://someurl.com/api/somefunction/' + data.smth.age);
});
}
Now the problem is that in func2 the data will be null or undefinded and it doesn't work after that.
In addition I have more than 2 functions which try to call getJSON.
I hope someone has a solution.
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 created some little jt code, but it gives me error
function Mind(){
var request = "request";
var reply = "reply";
var words = '';
this.Reply = function(){
if(request == words.nouns[0].noun){
reply = words.nouns[0].noun;
}
else
reply = this.words.nouns[0].noun;
}
this.SetRequest = function(req){
request = req;
}
this.GetReply = function(){
return reply;
}
this.Parse = function(u){
var xmlhttp = new XMLHttpRequest();
var url = u;
var result;
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
words = JSON.parse(xmlhttp.responseText);
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
return result;
}
this.Construct = function(){
words = this.Parse('mind/words.json');
}}
var mind = new Mind();
mind.Parse('mind/words.json');
and here is my json file
{
"nouns": [
{"noun": "child"},
{"noun": "father"}
]
}
In command live all goes well, but when I run this code, appears error
Uncaught TypeError: Cannot read property 'nouns' of undefined
Mutliple errors. The most fundamental one is that your code ignores that XMLHttpRequest is async, and wont return a value in the same way as "regular" functions. Read about it here: How to make a function wait until a callback has been called using node.js. The TL;DR is that you have to pass in a "callback-function" to your parse-method and "return" your value using that function, instead of using a return-statement. Google for "javascript callbacks" and read a few tutorials if this concept is new to you!
You also have some minor errors, like returning result from Parse, but never actually setting result to anything. Also words is being assigned in multiple places in a way that doesn't really make sense. But both of these things will go away when you solve the sync/async issues.
EDIT:
Essentially the fix looks like this:
this.Parse = function(u, callback){ // this "callback" is new
var xmlhttp = new XMLHttpRequest();
var url = u;
var result;
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
words = JSON.parse(xmlhttp.responseText);
callback(null, words); // we're "returning" the words here
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
// no return statement here!
}
this.Construct = function(){
this.Parse('mind/words.json', function(error, words) {
// here you can use your words!
});
}}
I am writing a piece of code that should catch all ajax responses on a page. I managed to do this by overriding XMLHttpRequest.onreadystatechange for javascript direct ajax or by using ajaxComplete() for jQuery ajax.
My problem happens when I try to use ajax multiple times without creating a new XMLHttpObject, for example:
var xhr = new XMLHttpRequest();
xhr.open("GET", '/echo/json/', true);
xhr.send();
xhr.open("GET", '/echo/json/', true);
xhr.send()
This makes my code go haywire and I get the maximum stack error.
Here is my testing code on JSFiddle: http://jsfiddle.net/zxCfW/
var s_ajaxListener = {};
s_ajaxListener.tmpSend = XMLHttpRequest.prototype.send;
s_ajaxListener.callback = function () {
console.log('additional state change');
};
XMLHttpRequest.prototype.send = function() {
s_ajaxListener.tmpOnReadyStateChange = this.onreadystatechange;
this.onreadystatechange = function() {
if (s_ajaxListener.tmpOnReadyStateChange){
s_ajaxListener.tmpOnReadyStateChange.apply(this, arguments);
}
if(this.readyState == 4 && this.status == 200) {
s_ajaxListener.callback();
this.onreadystatechange = s_ajaxListener.tmpOnReadyStateChange;
}
};
s_ajaxListener.tmpSend.apply(this, arguments);
};
$(document).ajaxComplete(s_ajaxListener.callback);
I believe this happens because the ajax calls are asynchronous so the original onreadystatechange doesn't reset to its default value, but I don't know how to solve this.