Code is not displaying JSON data - javascript

Hey guys I am trying to make a request to a JSON page, grabbing the data, then displaying it to my console but it is giving me "undefined". Why is that?
Here is the code and then the JSON page will be posted under it:
(function Apod() {
var api_key = 'NNKOjkoul8n1CH1NoUFo',
url = 'https://api.nasa.gov/planetary/apod' + "?api_key=" + api_key,
data;
var apodRequest = new XMLHttpRequest();
apodRequest.onreadystatechange = function() {
if (apodRequest.readyState === 4 && apodRequest.status === 200) {
var response = apodRequest.responseText;
var parsedAPOD = JSON.parse(response);
data += parsedAPOD;
for (i = 0; i < parsedAPOD.length; i++) {
data += parsedAPOD[i];
console.log("Parsing lines: <br>" + parsedAPOD[i]);
}
}
apodRequest.open("GET", url, true);
apodRequest.send(null);
}
}());
JSON page parsing:
{
"date": "2016-11-05",
"explanation": "Shot in Ultra HD, this stunning video can take you on a tour of the International Space Station. A fisheye lens with sharp focus and extreme depth of field provides an immersive visual experience of life in the orbital outpost. In the 18 minute fly-through, your point of view will float serenely while you watch our fair planet go by 400 kilometers below the seven-windowed Cupola, and explore the interior of the station's habitable nodes and modules from an astronaut's perspective. The modular International Space Station is Earth's largest artificial satellite, about the size of a football field in overall length and width. Its total pressurized volume is approximately equal to that of a Boeing 747 aircraft.",
"media_type": "video",
"service_version": "v1",
"title": "ISS Fisheye Fly-Through",
"url": "https://www.youtube.com/embed/DhmdyQdu96M?rel=0"
}

You have a few errors in your code.
First off, the general structure of it should be like this
(function Apod() {
var api_key = 'NNKOjkoul8n1CH1NoUFo',
url = 'https://api.nasa.gov/planetary/apod' + "?api_key=" + api_key,
data;
var apodRequest = new XMLHttpRequest();
apodRequest.onreadystatechange = function() {
//Code here
};
apodRequest.open("GET", url, true);
apodRequest.send(null);
}());
Notice how I moved apodRequest.open("GET", url, true); and apodRequest.send(null); outside of the onreadystatechange handler.
Secondly, instead of
apodRequest.onreadystatechange = function() {
if (apodRequest.readyState === 4 && apodRequest.status === 200) {
//Code here
}
}
you can simply do
apodRequest.onload = function() {
//Code here
};
As it's the event that will fire when a response is returned. So you don't need the if check inside.
Finally, inside the onload handler, you have a few mistakes, such as:
data += parsedAPOD; this is wrong because data is an object undefined up to this point and parsedAPOD is an object. Doing += between two objects will not merge them. If you want to merge two objects there are other ways, e.g. Object.assign
for (i = 0; i < parsedAPOD.length; i++) { ... } is wrong because parsedAPOD is an object. Objects do not have a length property, so this is not the correct way to iterate over it. Use for ... in ... loop instead
data += parsedAPOD[i]; is, again, wrong, because this is not the way to merge objects.
parsedAPOD[i] is wrong because i is an integer, in this case, so parsedAPOD[i] is simply undefined.
Hope this analysis helps you correct your code.

first of all parsedAPOD is an object and parsedAPOD.length is not valid. You can use for in loop to iterate through an object as below.
for (var i in parsedAPOD) {
data += parsedAPOD[i];
console.log("Parsing lines: <br>" + parsedAPOD[i]);
}

Related

Make changes of colors of icons visible in openlayers with a function

I try to accomplish that I will be able to change the color of marker icons to be visible in the map. They are in the map in different colors. Those colors are correspondenting to the json cat_id key's.
1: "http://dev.openlayers.org/img/marker.png",
2: "http://dev.openlayers.org/img/marker-blue.png",
3: "http://dev.openlayers.org/img/marker-gold.png",
4: "http://dev.openlayers.org/img/marker-green.png",
Each marker icon that is in the map is getting it's position, color and other valuable data from the json objects in the data id in the script tag. I didn't code the part of that work's close with the openlayer libary's. I wrote the following part of the total of the script:
var json = document.getElementById('data').innerHTML;
json = JSON.parse(json); // converts text into JSON
// search criteria (could be changed)
var $search_postal = "8912JB";
var $search_number = "10";
var $change_cat = 1;
function changeColor() {
for (var key in json) {
if (json.hasOwnProperty(key)) {
if (json[key].postal == $search_postal) {
if (json[key].number == $search_number) {
alert("Gonna change cat_id " + json[key].cat_id + " of the number search string " + $search_number + " of the postal search string " + $search_postal + " to cat_id " + $change_cat);
json[key].cat_id = "1";
alert('Changed!');
const posts = json; // the constant that is used to display the icons
var myJSON = json;
document.getElementById('demo').innerHTML = JSON.stringify(myJSON, undefined, 2); // changes of the json data to see on screen
}
}
}
}
}
const posts = json; //the constant that is used to display the icons
var myJSON = JSON.stringify(json);
document.getElementById('demo').innerHTML = myJSON;
This script will change the cat_id of the given search input. In the example it does a search for postal 8912JB with number 1. Once it has made the loop to find it's position it will change the cat_id value of 3 to 1. In other words the json data has been changed. Since it is stored in the const posts I replace this cons with the changed data. My problem is that I'm unable to refresh the marker icon(s) in the map with the new json data that is changed (cat_id: 1 of postal 8912JB number 10). This has to do with less knowledge about openlayers and Javascript. I'm struggling already 2 weeks with this. Can anybody help me to accomplish this? If it changes from color is the only thing that is required. I would only need to give the changes to the variables $search_postal, $search_number and $change_cat.
Here is the page for debug: https://jsfiddle.net/j4z1vpht/4/
Thanks for any help,
grid
You need to update the new category to the map feature, like this:
const updateFeatureCategory = (featureId, categoryId) => {
const feature = marker_layer.getSource().getFeatureById(featureId);
const post = feature.get("post");
const updatedPost = {
...post,
cat_id: categoryId
}
feature.set("post", updatedPost);
}
function changeColor() {
...
json[key].cat_id = "1";
updateFeatureCategory(key, "1");
...
}
Here's a working fiddle: https://jsfiddle.net/wsm2h3qz/1/

Split a JSON array into JS variables - Bixby

So I have a API outputting JSON to my JS code (http://api.opentripmap.com/0.1/ru/places/bbox?lon_min=-123.049641&lat_min=37.550392&lon_max=-122.049641&lat_max=38.550392&kinds=foods&format=geojson&apikey=5ae2e3f221c38a28845f05b685eac8210f10fb196793a9d4f6653c25).
However it contains a JSON Array that looks like this- "coordinates": [ -122.510216, 37.769474 ]
Is there a way to split it into separate JS variables like one variable for the left side and another for the right side. At the moment the array is causing my code to crash as it can only accept one input in each slot.
Sorry If this is a simple question, I haven't been able to solve this yet...
EDIT:
Sorry for the terrible question layout. I have tried to splice and splitting the array with no success (splicing lead to a whole load of undefined errors).
My current code is
module.exports.function = function findLunch(myLocation) {
var loc_long_max = Number(myLocation.longitude) //grab longitude from user
var loc_lat_min = Number(myLocation.latitude) //grab latitude from User
var loc_long_min = loc_long_max - 0.5;
var loc_lat_max = loc_lat_min + 0.5;
var url_all = "http://api.opentripmap.com/0.1/ru/places/bbox?lon_min=" + loc_long_min + "&lat_min=" + loc_lat_min + "&lon_max=" + loc_long_max + "&lat_max=" + loc_lat_max + "&kinds=foods&format=geojson&apikey=5ae2e3f221c38a28845f05b685eac8210f10fb196793a9d4f6653c25"
var results = http.getUrl(url_all, { format: 'json' }); //gets json info from url_all.
console.log(results.features[rand].properties.name)
//console.log(results.feautres[rand].properties.rate)
console.log(results.features[rand].geometry.coordinates)
//console.log(results);
for (var i = rand; i < results.features.length; i++) {
console.log(results.features[rand].properties.name)
console.log(results.features[rand].properties.rate)
var businesses = {
name: results.features[rand].properties.name,
rating:results.features[rand].properties.rate,
coordinates: results.features[rand].geometry.coordinates
}
}
return businesses
So the coordinates need to be split and then be in the businesses var which is then outputted to Bixby....
EDIT 2 : Fixed it - thanks everyone for the help!
Thanks!
Not sure if this is smth you're asking but you can use destructuting assignment to assign items in an array to variables:
const coordinates = [ -122.510216, 37.769474 ];
const [coordinateOne, coordinateTwo] = coordinates;
console.log(coordinateOne) // -122.510216
console.log(coordinateTwo) // 37.769474
You can use destructuring to assign the first and second elements of the array to variables in a simple way:
const coordinates = [-122.510216, 37.769474];
const [left, right] = coordinates;
console.log(left);
console.log(right);

Separate data from text file using Javascript

I'm working on creating an analytics page that uses data stored in a text file. The text file is used for my highcharts graph and is separated like so:
November 7th 6AM,19.8
November 7th 6PM,19.8
November 8th 6AM,20.4
November 8th 6PM,14.6
November 9th 6AM,15.9
November 9th 6PM,15.1
November 10th 6AM,16.4
November 10th 6PM,16.4
I'm looking to separate that data into 12 calendar panes that will display overall discrepancies for each month. For example, if a date had the value 16, and then it dropped to 10 the next reading, to take a cumulative sum for how many times that happened for the month.
How do I make sure that it reads from the text file in proper order and that it checks to see if the next value went below 10 and tallies that somewhere?
Yo can use jQuery to separate the file data into array.
$(document).ready(function() {
//fetch text file
$.get('text.txt', function(data) {
//split on new lines
var lines = data.split('\n');
for(var i=0;i<lines.length;i++) {
// use lines[i] the way you want
}
});
});
Then you can use this to get sub-strings:
var a = s.indexOf(',');
var b = s.substring(a,4);
This way you can separate the data and use it as desired.
You need to
Fetch the data file
One usually does this with AJAX (XMLHttpRequest)
Separate your datapoints
Your data seems to be neat enough that you can, for every line in the file, get the name of the month with line.split(" ")[0] and the value with line.split(",")[1]. Splitting a text to lines can usually be as easy as text.split("\n").
Iterate over results
For every month-value pair you now have, compare the name of the months. If it is a match and the value has changed by x, increment a value in your books, e.g. discrepancies[monthName]++. Save the name-value pair and continue.
Example:
// Get the data
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) { // If the request is complete with status code "OK"
handleImportantData(req.responseText);
}
};
// Define the request to be using the method GET to an URL asynchronously.
req.open("GET", "important_data.txt", true);
req.send();
function handleImportantData(data) {
var treshold = 5.0;
var months = {};
var discrepancies = {};
// Separate data points.
var lines = data.split("\n");
lines.forEach(function(line) {
// The || 0.0 part sets the value to zero if our data is malformed.
// We parse the value as a float to prevent it being saved as a string,
// which would make arithmetic operations on it not work as expected.
months[line.split(" ")[0]] = parseFloat(line.split(",")[1]) || 0.0;
});
// Find discrepancies.
var previous = {
name: "",
value: 0.0
};
for (var name in months) {
// If not already there, initialize the data point with ternary operation including NOP.
discrepancies[name] ? {} : discrepancies[name] = 0.0;
// If we're still talking about the same month as before and the value
// has changed for more than our treshold, save it as a discrepancy.
if name === previous.name && Math.abs(previous.value - months[name]) > treshold {
discrepancies[name] ++;
}
previous = {
name: name,
value: months[name]
}; // Set this as the previous value.
}
// Here we have ready discrepancy data stored in the variable discrepancies.
}

From SQL one-to-many to Parse NoSQL

I have always used MySQL for database and seeing that joins are twisted with Parse API for NoSQL, I believe I have a flaw with the design of my database.
Here is what I use :
Game
---------
id
userA
userB
currentRound
RoundScore // A Game can have 0-3 RoundScore
---------
id
game -> Pointer field to Game
user
round
score
(There is also a default User collection with Parse and all user-related fields inside Game and RoundScore point to the User collection. This works great).
Seeing how the Parse API works, I found it difficult to make the query :
Get all Games and their (up to 3) Rounds' score where Game.userA = me or Game.userB = me.
I could easily get all Games but without their Rounds' score. I can't join both.
How should I handle this query or the design ?
Should I fuse the RoundScore into the Game collection ? If so, how should I declare the new field ?
I have read all these pages:
https://parse.com/docs/js_guide#queries
https://www.parse.com/questions/how-to-achieve-or-condition-in-query
https://parse.com/questions/combining-queries-or-not-and-modeling-relationships
https://www.parse.com/docs/js/symbols/Parse.Query.html
I am of the opinion that the following code snippet should work for you:
var RoundScoreQuery = new Parse.Query("RoundScore");
var userAQuery = new Parse.Query("Game");
userAQuery.equalTo("userA", "me");
var userBQuery = new Parse.Query("Game");
userBQuery.equalTo("userB", "me");
var gamesQuery = Parse.Query.or(userAQuery, userBQuery);
gamesQuery.find({
success: function(results) {
// results contains all games where "me" is a part of
for (var i = 0; i < results.length; i++) {
var gameId = results[i].get("id");
RoundScoreQuery.equalTo("game", gameId);
query.first({
success: function(object) {
// Successfully retrieved the object with the score
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
}
},
error: function(error) {
// There was an error.
}
});
Okay, that's a good point.
I would create the Game Object like this (https://parse.com/docs/js_guide#objects):
var id = 1; // game #1
var userA = "Name A";
var userB = "Name B";
var score1 = { user: "Name A", score: 3 }; // round one
var score2 = { user: "Name B", score: 5 }; // round two
var score3 = null; // round three
var Game = Parse.Object.extend("Game");
var game = new Game();
game.set("id", number);
game.set("userA", userA);
game.set("userB", userB);
game.set("ScoreR1", object);
game.set("ScoreR2", object);
game.set("ScoreR3", object);
game.save();
The flag "currentRound" is no longer needed
because you know what's the current round is
when you look at ScoreR1, ScoreR2 and ScoreR3.
Now you should only need this code to get all the games where "me" is part from:
var userAQuery = new Parse.Query("Game");
userAQuery.equalTo("userA", "me");
var userBQuery = new Parse.Query("Game");
userBQuery.equalTo("userB", "me");
var gamesQuery = Parse.Query.or(userAQuery, userBQuery);
gamesQuery.find({
success: function(results) {
// results contains all games where "me" is a part of
},
error: function(error) {
// There was an error.
}
});
For more info about "NoSQL Design Patterns for Relational Data", I would recommend this article:
http://robvolk.com/designing-for-relationships-on-a-no-sql-database/
2 ways of doing this:
use pointers from 'game' to 'score' so that you can flatten the query with 'include=' syntax.
Note they even use "games" in the docs example!
Or leverage noSql arrays to flatten your physical design:
Game
---------
id
userA -> type:Array:"scores":["123","234","345"] <-- handle null array
userB -> type:Array:"scores":["321","242","325"]
Just say the Game scores are an array that belong to "game/user"
Just say Game consists of 2 sets of "userScores" which are arrays
IMO you want to come up with a noSql compatible way of dealing with your models and their collections in your MVC mechanism so you can always template it neatly by coming out of your Parse.com API calls with JSON structs that you can easily parse and feed appropriate JSON Objects to whatever template you use for ( JSON to model Obj Classes & Collections ).
example i guess even tho java it may give idea for ios

Efficient way of sending a large bit stream in an HTTP response

I need to send large string representing a number over a wire to the client written in Java Script. In theory it's a stream of 0s and 1s, like: 011101011101101..., but it can be very, very big (millions of bits in length). My goal, of course, is to minimize necessary processing and sending overhead. I thought about changing the base number of that string, so that it uses HEX or larger radix which would greately reduce the amount of data that has to be sent. JavaScript has built in functions for converting to and from different numbering systems so it looked like the way to go. However, the maximum supported radix is just 36. My calculations are showing that when having a stream of 50 mln bits and using 36 radix, then you still need 1,388,888 characters to be sent - way too much.
My question is - do you know any way that would help to achieve my goal? Some constraints:
Solution must work for streams of arbitrary length
bit streams can be as large as 50mln bits
Good performance should be guaranteed for length around 1-10mln bits. For larger streams it should still work, however it doesn't have to scale up linearly
I would put more emphasis on optimizing the amount of data that has to be sent, not necessarily on reducing the CPU overhead
You could do something like this (the demo has been written with no way of testing it, but it "should work™", here is a fiddle for those who wants to copy/cut/paste: http://fiddle.jshell.net/sywz3aym/2/
Please note the fiddle can't run, i had intended to write a responder but i can't right now i'm afraid.
At the bottom of the javascript entry area i have comment section of how a asp.net responder could look, it uses a "Generic Handler (.ashx)" file if you use visual studio, if you use any other language you will have to use the equivalent options there. You need a request responder which you can customize to return binary data, you need to set the Content-Type to "application/octet-stream" (octet for those who do not know = "group of 8", eg. a byte :))
And here is the javascript + comment as in a glorious wall of text format:
$(document).ready(function () {
var url = 'your handler URL';
var oReq = new XMLHttpRequest();
oReq.open('GET', url, true);
oReq.responseType = 'arraybuffer';
oReq.onload = function (oEvent) {
var buffer = oReq.response;
var yourData = ExtractData(buffer);
}
oReq.send(null);
});
function ExtractData(buffer) {
var dataReader = {
dataView: new DataView(buffer),
readPtr: 0,
littleEndian: (function () {
var buffer = new ArrayBuffer(2);
new DataView(buffer).setInt16(0, 256, true);
return new Int16Array(buffer)[0] === 256;
})(),
setReadPtrOffset: function (byteIndex) {
this.readPtr = byteIndex;
},
nextInt8: function () {
var data = this.dataView.getInt8(this.readPtr);
this.readPtr += 1; // Sizeof int
return data;
},
nextUint8: function () {
var data = this.dataView.getUint8(this.readPtr);
this.readPtr += 1; // Sizeof int8
return data;
},
nextInt32: function () {
var data = this.dataView.getInt32(this.readPtr, this.littleEndian);
this.readPtr += 4; // Sizeof int32
return data;
},
nextUint32: function () {
var data = this.dataView.getUint32(this.readPtr, this.littleEndian);
this.readPtr += 4; // Sizeof uint32
return data;
},
nextFloat32: function () {
var data = this.dataView.getFloat32(this.readPtr, this.littleEndian);
this.readPtr += 4; // Sizeof float
return data;
},
nextFloat64: function () {
var data = this.dataView.getFloat64(this.readPtr, this.littleEndian);
this.readPtr += 8; // Sizeof double
return data;
},
nextUTF8String: function (length) {
var data = String.fromCharCode.apply(null, new Uint8Array(this.dataView.buffer, this.readPtr, length));
this.readPtr += length; // Sizeof int
return data;
},
}
var numberOfInt32ToRead = dataReader.nextInt32(); // First data could be, for example, the number of ints to read.
for(var i = 0; i < numberOfInt32ToRead; i++){
var someInt = dataReader.nextInt32();
// doStuffWithInt(someInt);
}
}
/*
Serverside code looks kind of like this (asp.net/c#):
public class YourVeryNiceDataRequestHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/octet-stream"; // <- very important
List<int> data = SomeMethodWithGivesYouData();
context.Response.BinaryWrite(BitConverter.GetBytes((int)data.Count)); // Explicit type casting only to help me get an overview of the data being sent, in this case it has no functional meaning other then to help me debug
foreach(int i in data)
{
context.Response.BinaryWrite(BitConverter.GetBytes((int)i));
}
// You could send structs as well, either with the help of a binary formatter, or you can do like i did here and use BitConverter.GetBytes, be carefull when sending strings/chars since they are by default (usually) in a widechar format (1 char = 2 bytes), since i only use english for this i can convert it to a UTF8 char (1 byte): context.Response.BinaryWrite(System.Text.Encoding.UTF8.GetBytes(new char[] { (motion.Phase == Phases.Concentric ? 'C' : 'E') })); // Phase (as single char)
}
}
*/
I hope this either help you directly, or guide you in the correct direction.
Please note this is VERY dependent on your data types that your server use, and might not fall into your "REST" category, you did however state that you wanted to optimize for stream size and this afaik is the best way to do that, with the exception of adding data compression
Javascript typed arrays "mimics" c-style datatypes, like those used in c, c++, c#, java and so forth
Disclamer:
I have not tried this with data > 1MB, it did however cut the total size of data being sent from server to client from 2MB down to a few 10-100~KB, and it for the amount of data i send/read the execution time were "not humanly measurable" other then the roundtrip time for the extra request, since this is requested AFTER the page is loaded in the browser
Final word of warning: Any manual bit serializing/deserializing should be done with care, since it is very easy to make a mistake forgetting that you have changed something either client or server side, and it will give you un-debuggable garbage if you read or write a byte too much/too little on either end, this is why i add explicit type casting in my server-side code, that way i can open both the server code and the client code side-by-side and match readInt32 to a Write((int)...).
Not a fun job, but it makes things very compact and very fast (normally i would go for readability, but some tasks just have to work faster then readable code).
Typed arrays can't be used in every browser however, but caniuse state that 85% of the internet could use them: http://caniuse.com/#feat=typedarrays

Categories

Resources