I am trying to parse the content of the JSON file into a variable called weatherArray. However, this variable is always an empty array.
let weatherArray = [];
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
weatherArray = JSON.parse(this.responseText);
}
};
xhttp.open("GET", "https://fcc-weather-api.glitch.me/api/current?lon=55&lat=12", true);
xhttp.send();
}
/* Expecting the value to be stored and be shown in console*/
console.log(weatherArray);
You're checking the results before they come back. You need to move the line:
console.log(weatherArray);
To inside the onreadystatechange function, which will check the results once they arrive. Also you need to call the loadDoc() function (you probably did that).
let weatherArray = [];
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
weatherArray = JSON.parse(this.responseText);
console.log(weatherArray);
}
};
xhttp.open("GET", "https://fcc-weather-api.glitch.me/api/current?lon=55&lat=12", true);
xhttp.send();
}
loadDoc();
EDIT If you like to process the results in another function instead of inside onreadystatechange, you can call that function from onreadystatechange. You can do that with your global weatherArray, but I just recommend in this case to simply pass the data in a parameter:
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
showWeather(JSON.parse(this.responseText));
}
};
xhttp.open("GET", "https://fcc-weather-api.glitch.me/api/current?lon=55&lat=12", true);
xhttp.send();
}
function showWeather(weatherArray) {
console.log(weatherArray);
}
loadDoc();
Ajax is asynchronous call, and you are printing data before invoking the ajax call,
I made some changes try it.
let weatherArray = [];
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
weatherArray = JSON.parse(this.responseText);
console.log(this.responseText);
}
};
xhttp.open("GET", "https://fcc-weather-api.glitch.me/api/current?lon=55&lat=12", true);
xhttp.send();
}
loadDoc();
/* Expecting the value to be stored and be shown in console*/
I'd like to provide an alternative modern approach using the Fetch api and Promises.
First fetch from the api
Convert it to json
Return the promise
Listen for the promise and log the result in the callback
function loadDoc() {
return fetch("https://fcc-weather-api.glitch.me/api/current?lon=55&lat=12")
.then(res => res.json())
}
loadDoc().then((weatherArray) => {
console.log(weatherArray);
})
Related
I tried to implement cookie logging with localStorage into the javascript code for replacing a specific element. It uses the XMLHttprequest method and, I got no idea why it won't work with localStorage. Please enlighten me.
localStorage.setItem("replace1", this.JSON.parse(responseText));
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("replace1").innerHTML = localStorage.getItem("replace1");
}
};
xhttp.open("GET", "yoinkexecutor2.php", true);
xhttp.send();
}
You can only display data when the async operation (GET) request terminates.
Otherwise you'll get undefined since nothing exits in the localStorage under that key
Also, you can only store strings in local storage, meaning you need to parse that object string once you want to retrieve the data using getItem
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
localStorage.setItem("replace1", JSON.stringify(this.responseText))
document.getElementById("replace1").innerHTML = JSON.parse(localStorage.getItem("replace1"))
}
};
xhttp.open("GET", "yoinkexecutor2.php", true);
xhttp.send();
}
I am polling a database.
see the "<--------------" in the code below.
This works:
class MultiplayerGame{
...
...
callPhpWithAjax(url){
var xmlhttp = new XMLHttpRequest();
var instance = this;
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
instance.pollResponse(this.responseText); <-----------works, pollResponse is called and I can access the object with "this"
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
poll(){
var url = "myurl.com"
this.callPhpWithAjax(url);
}
pollResponse(response){
this.variable = response;
}
}
When I try to implement it a bit more generic, it doesn't work:
class MultiplayerGame{
...
callPhpWithAjaxGenericNOTWORKING(url,callbackfunction){
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
callbackfunction(this.responseText); <----------callbackfunction not calling what I wanted.
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
poll(){
var url = "myurl.com"
this.callPhpWithAjaxGenericNOTWORKING(url, this.pollResponse); <--------------- it seems like this.pollResponse is not ok. I don't know how to do it.
}
pollResponse(response){
this.variable = response; <----- this.variable is undefined. (this is not the class instance i was hoping)
}
When I call the function with the callbackfunction, I use "this", but apparently, it does not reference the same object. I am confused here.
How do I send the callbackfunction correctly as a paramenter?
Add .bind(this) when using an object's method as a callback parameter.
So your code inside poll should be
this.callPhpWithAjaxGenericNOTWORKING(url, this.pollResponse.bind(this))
See Function.prototype.bind()
hi after searching in the net about how to use the long polling in JavaScript I ended up with three ways, they are mentioned here briefly,but they are implemented using JQuery. I am confused which one to use in case that the AJAX request that I send to the server is asynchronous GET request ,and I don't know how many time it could take.
here is an example AJAX request:
function asynchGETRequest(method,url){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log("ok");
}
};
xhttp.open(method, url, true);
xhttp.send();
return (xhttp.responseText);
}
var clientFunctions={
getAnswers : function(callback){
var res=asynchGETRequest("GET", "http://localhost:9000/answers");
callback(JSON.stringify(res));
}
}
clientFunctions.getAnswers (function(){
//do some code here after the ajax request is ended
});
can some one guide me please?
I think I found the solution here
function loadFile(sUrl, timeout, callback){
var args = arguments.slice(3);
var xhr = new XMLHttpRequest();
xhr.ontimeout = function () {
console.error("The request for " + url + " timed out.");
};
xhr.onload = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
callback.apply(xhr, args);
} else {
console.error(xhr.statusText);
}
}
};
xhr.open("GET", url, true);
xhr.timeout = timeout;
xhr.send(null);
}
I have an xhttp function that calls my db and returns an array, the array is different depending on the parameter passed in the xhttp function when called.
This is the xhttp function I have:
fetchGroupInfo: function (groupNum) {
var global = this;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() { //(callback function)this function runs after xhttp.open because we have asynchronous data sending so as soon as the data is recieved this is run
if (xhttp.readyState === XMLHttpRequest.DONE && xhttp.status == 200) {
console.log(this.responseText);
//I parse the rawdata received into jason structure then I pass it into and call the manipulate function
var rawdata = this.responseText;
var json = JSON.parse(rawdata); //parses the query result
return json;
}
};
xhttp.open("GET", "http://178.62.***.***:1020/groupInfo/"+groupNum, true);
xhttp.send();
},
Since I need to call the function 8 times on page load and get back 8 different arrays, I do not want to have to write out this function 8 times for each different array I need to get back. what I would like to be able to do later is something like this, so that I can keep my code clean:
this.group1Info = this.fetchGroupInfo(1);
this.group2Info = this.fetchGroupInfo(2);
this.group3Info = this.fetchGroupInfo(3);
this.group4Info = this.fetchGroupInfo(4);
.....
At the moment the way that the function is set up it is returning an undefined value, how would I make this work?
Your code is asynchronous, so you'll you to add a callback function and then set your variables in the callback:
fetchGroupInfo: function (groupNum, callback) {
var global = this;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() { //(callback function)this function runs after xhttp.open because we have asynchronous data sending so as soon as the data is recieved this is run
if (xhttp.readyState === XMLHttpRequest.DONE && xhttp.status == 200) {
console.log(this.responseText);
//I parse the rawdata received into jason structure then I pass it into and call the manipulate function
var rawdata = this.responseText;
var json = JSON.parse(rawdata); //parses the query result
return callback(json);
}
};
xhttp.open("GET", "http://178.62.***.***:1020/groupInfo/"+groupNum, true);
xhttp.send();
}
and now to set the variables, pass a callback each time you call fetchGroupInfo:
this.fetchGroupInfo(1, function(result) {
this.group1Info = result;
});
I have been trying to parse a bit of JSON from an API now and it was all working when I used
xmlHttp.open('GET', url, false);
But when I later wanted to expand my code using timeouts for the requests my function started to return empty values.
This is the function doing the actual parsing:
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
obj = JSON.parse(xmlHttp.responseText);
console.log(obj);
}
}
};
When I log the object returned here using console.log I get the JSON printed out to the console normally but later in my function I am returning the obj variable but it is always empty.
Here is the whole function:
static Parse(url: string): Object{
Asserts.isUrl(url, 'URL is invalid');
var obj = new Object();
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
obj = JSON.parse(xmlHttp.responseText);
//console.log(obj);
}
}
};
xmlHttp.open('GET', url, true);
xmlHttp.timeout = 2000;
xmlHttp.ontimeout = function () {
xmlHttp.abort();
throw new Error("Request Timed Out.");
};
xmlHttp.send();
return obj;
}
My first thought that it had something to do with the scope in Javascript but now after being stuck here for a few hours without progress I am clueless.
As I mentioned inside the xmlHttp.onreadystatechange = function () the console.log is actually logging the correct value. It's just that the obj variable created at the start of the function is not getting the value.
AJAX is asynchronous. This means that the onreadystatechange function will be called at a much later stage, probably after you have already returned from the Parse method. So you should not be trying to return obj from the Parse method. You would rather have the Parse method take an additional parameter that represents a callback function which you will invoke inside the onreadystatechange event and pass it the resulting object.
Here's what I mean:
static Parse(url: string, done: (obj: any) => void): void {
Asserts.isUrl(url, 'URL is invalid');
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var obj = JSON.parse(xmlHttp.responseText);
// Pass the resulting object to the callback function
done(obj);
}
}
};
xmlHttp.open('GET', url, true);
xmlHttp.timeout = 2000;
xmlHttp.ontimeout = function () {
xmlHttp.abort();
throw new Error("Request Timed Out.");
};
xmlHttp.send();
}
and here's how you would call the Parse function:
Parse('http://foobar', function(obj) => {
// TODO: do something with obj here
console.log(obj);
});
So basically when you are writing a javascript application that uses asynchronous AJAX calls you should stop thinking in terms of sequential functions that you will invoke one after the other and which will return values. You should start thinking in terms of callbacks.
You need to pass a callback to the function:
static Parse(url: string, onSuccess: Function): Object{
Asserts.isUrl(url, 'URL is invalid');
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var obj = new Object();
obj = JSON.parse(xmlHttp.responseText);
onSuccess(obj)
}
}
};
xmlHttp.open('GET', url, true);
xmlHttp.timeout = 2000;
xmlHttp.ontimeout = function () {
xmlHttp.abort();
throw new Error("Request Timed Out.");
};
xmlHttp.send();
}
and call the function with your callback parameter.