Node.js Cannot read property of undefined using JSON data - javascript

I'm trying to convert a js script to a node.js script. The JS script works fine, and managed to pull data from this URL and correctly use the information. However, when I try run it on Node.js, I get the error "Cannot read property of 'fixtures' undefined."I've added this package to pull the data, however I'm not sure why it's now throwing an error.
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
var xhr = new XMLHttpRequest();
//Get Data
var getJSON = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status === 200) {
callback(null, xhr.response);
} else {
callback(status, xhr.response);
}
};
xhr.send();
};
//Use Data
getJSON('http://api.football-data.org/v1/teams/343/fixtures',
function(err, data) {
if (err !== null) {
console.log(" An error has occured.")
} else {
var latest;
for(x = 0; data.fixtures[x].status !== "TIMED"; x++) {
latest = data.fixtures[x].matchday - 1;
}
}};
The error is thrown at the line while(data.fixtures[x].status !== "TIMED"), and the error is
for(x = 0; data.fixtures[x].status !== "TIMED"; x++) {
^
TypeError: Cannot read property 'fixtures' of undefined
Please could you explain to me why JS can see the data and use it fine, but node.js sees the property to be undefined?
Many thanks.
EDIT: Removed legacy while loop that shouldn't have been there.

The reason you're getting that message is because the variable data in your callback is undefined. The reason it is so is that you are passing it that
callback(null, xhr.response); //<-- You should have used responseText
But even that will not solve the issue - it is text not json. So parse it
callback(null, JSON.parse(xhr.responseText));

The response property is part XMLHttpRequest Level 2, but xmlhttprequest only supports 1 at the moment:
Note: This library currently conforms to XMLHttpRequest 1.
For this reason xhr.response will be undefined.
Only xhr.responseText will be set, and this is a string so you would need to add the parsing of json yourself.
if (status === 200) {
try { // use a try block here in case the the response is not parseable
callback(null, JSON.parse(xhr.responseText));
} catch(e) {
callback(e)
}
} else {
callback(status, xhr.response);
}

Related

Slim cropper works perfectly fine on my localhost, but gives a 403 forbidden error on server

I'm using slim cropper to upload avatar's on my codeigniter project , It works perfectly on my localhost but on the server , the ajax call to the php that does the image upload keeps giving a 403 forbidden error, below is the section of the code:
function send(url, data, progress, success, err) {
var xhr = new XMLHttpRequest();
if (progress) {
xhr.upload.addEventListener('progress', function (e) {
progress(e.loaded, e.total);
});
}
xhr.open('POST', url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var text = xhr.responseText;
// if no data returned from server assume success
if (!text.length) {
success();
return;
}
// catch possible PHP content length problem
if (text.indexOf('Content-Length') !== -1) {
err('file-too-big');
return;
}
// if data returned it should be in suggested JSON format
var obj = null;
try {
obj = JSON.parse(xhr.responseText);
} catch (e) {}
success(obj || text);
} else if (xhr.readyState === 4) {
err('fail');
}
};
xhr.send(data);
}
From what I've read , providing a CSRF token might solve the problem, but the request is made from the same domain and I don't require that on my localhost. What could be the problem?

Youtube API v3 get the Channel ID of user that uploaded a certain video

I want to get the channel ID of a user that uploaded a certain YouTube video on javascript to after that comparing the channel id to see if it's in an array.
The thing is, I can't find exactly how to get that from javascript. I tried to get:
https://www.googleapis.com/youtube/v3/videos?part=snippet&id=[Video ID]&key=[my key]
but it gives me JSON parsing error on every video.
Anyone knows how to do it exactly using YouTube API? Doesn't matter if I have to add an exteral script on the html part.
And, as an example of what I want to do, for this video:
https://www.youtube.com/watch?v=jNQXAC9IVRw
it should return 'UC4QobU6STFB0P71PMvOGN5A'.
Any idea on how to do it?
I took the Ajax code from youmightnotneedjquery.com and edited it a bit to make a getJSON utility function. This worked for me:
var API_KEY = 'YOUR_API_KEY'; // Replace this with your own key
getJSON(
'https://www.googleapis.com/youtube/v3/videos?part=snippet&id=jNQXAC9IVRw&key=' + API_KEY,
function (err, data) {
if (err) {
alert(err);
} else {
alert(data.items[0].snippet.channelId);
}
}
);
function getJSON(url, callback) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
// We have the JSON, now we try to parse it
try {
var data = JSON.parse(request.responseText);
// It worked, no error (null)
return callback(null, data);
} catch(e) {
// A parsing arror occurred
console.error(e);
return callback('An error occurred while parsing the JSON.');
}
}
// If an error occurred while fetching the data
callback('An error occurred while fetching the JSON.');
};
request.onerror = function() {
// There was a connection error of some sort
callback('An error occurred while fetching the JSON.');
};
request.send();
}

How to have javascript read a JSON URL

I want my javascript file to search a URL that is a JSON and grab specific contents from the page. This is the URL
And I want to grab the averageratingscore_rf.
I've even tried this :
var getJSON = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status === 200) {
callback(null, xhr.response);
} else {
callback(status, xhr.response);
}
};
xhr.send();
};
getJSON('https://search.mtvnservices.com/typeahead/suggest/?solrformat=true&rows=20&callback=noCB&q=burgos+AND+schoolid_s%3A1262&defType=edismax&qf=teacherfirstname_t%5E2000+teacherlastname_t%5E2000+teacherfullname_t%5E2000+autosuggest&bf=pow(total_number_of_ratings_i%2C2.1)&sort=total_number_of_ratings_i+desc&siteName=rmp&rows=20&start=0&fl=pk_id+teacherfirstname_t+teacherlastname_t+total_number_of_ratings_i+averageratingscore_rf+schoolid_s&fq=',
function(err, data) {
if (err !== null) {
alert('Something went wrong: ' + err);
} else {
console.log(data.response.docs.averageratingscore_rf);
}
});
But this doesn't work.
It's not a json, it's jsonp response.
JSONP requests perfomed by pass callback name and load this url into DOM script tag.
just don't try ajax+eval, anyway CORS restricts ajax here
Also, data.response.docs is an array, you should iterate it to access averageratingscore_rf
let cb = 'mycallback';
let url = `https://search.mtvnservices.com/typeahead/suggest/?solrformat=true&rows=20&callback=${cb}&q=burgos+AND+schoolid_s%3A1262&defType=edismax&qf=teacherfirstname_t%5E2000+teacherlastname_t%5E2000+teacherfullname_t%5E2000+autosuggest&bf=pow(total_number_of_ratings_i%2C2.1)&sort=total_number_of_ratings_i+desc&siteName=rmp&rows=20&start=0&fl=pk_id+teacherfirstname_t+teacherlastname_t+total_number_of_ratings_i+averageratingscore_rf+schoolid_s&fq=`
function mycallback(data) {
let res = data.response.docs.map(doc => doc.averageratingscore_rf)
console.log('averageratingscore_rf of docs:', res);
}
let script = document.createElement('script');
script.src = url;
document.body.appendChild(script)
Your URL is for JSONP, removing the callback argument returns JSON. (Remove callback=noCB)
Since you tagged google-chrome-extension Same Origin Policy may not apply but keep in mind Cross Origin Resource Sharing may need to be enabled.
... or you could handle the JSONP
Your URL isn't giving back pure JSON. There's a noCB() function wrapping it. That's probably why it's not being read.
Here's what I saw when I opened the URL:
noCB({ "responseHeader":{ "status":0, "QTime":1}, "response":{"numFound":1,"start":0,"docs":[ { "teacherlastname_t":"Burgos", "pk_id":282380, "schoolid_s":"1262", "averageratingscore_rf":2.47, "total_number_of_ratings_i":125, "teacherfirstname_t":"Fernando"}] }, "spellcheck":{ "suggestions":[]}} );
You may be able to execute that method, but if you only want the json, you can either strip out the "noCB(" and ");" at the beginning or the end when you get it, or strip it out at the server.

What is the vanilla JS version of Jquery's $.getJSON

I need to build a project to get into a JS bootcamp I am applying for. They tell me I may only use vanilla JS, specifically that frameworks and Jquery are not permitted. Up to this point when I wanted to retrieve a JSON file from an api I would say
$.getJSON(url, functionToPassJsonFileTo)
for JSON calls and
$.getJSON(url + "&callback?", functionToPassJsonPFileTo)
for JSONP calls. I just started programming this month so please bear in mind I don't know the difference between JSON or JSONP or how they relate to this thing called ajax. Please explain how I would get what the 2 lines above achieve in Vanilla Javascript. Thank you.
So to clarify,
function jsonp(uri){
return new Promise(function(resolve, reject){
var id = '_' + Math.round(10000 * Math.random())
var callbackName = 'jsonp_callback_' + id
window[callbackName] = function(data){
delete window[callbackName]
var ele = document.getElementById(id)
ele.parentNode.removeChild(ele)
resolve(data)
}
var src = uri + '&callback=' + callbackName
var script = document.createElement('script')
script.src = src
script.id = id
script.addEventListener('error', reject)
(document.getElementsByTagName('head')[0] || document.body || document.documentElement).appendChild(script)
})
}
would be the JSONP equivalent?
Here is the Vanilla JS version for $.getJSON :
var request = new XMLHttpRequest();
request.open('GET', '/my/url', true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
// Success!
var data = JSON.parse(request.responseText);
} else {
// We reached our target server, but it returned an error
}
};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
Ref: http://youmightnotneedjquery.com/
For JSONP SO already has the answer here
With $.getJSON you can load JSON-encoded data from the server using
a GET HTTP request.
ES6 has Fetch API which provides a global fetch() method that provides an easy, logical way to fetch resources asynchronously across the network.
It is easier than XMLHttpRequest.
fetch(url) // Call the fetch function passing the url of the API as a parameter
.then(res => res.json())
.then(function (res) {
console.log(res)
// Your code for handling the data you get from the API
})
.catch(function() {
// This is where you run code if the server returns any errors
});
Here is a vanilla JS version of Ajax
var $ajax = (function(){
var that = {};
that.send = function(url, options) {
var on_success = options.onSuccess || function(){},
on_error = options.onError || function(){},
on_timeout = options.onTimeout || function(){},
timeout = options.timeout || 10000; // ms
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//console.log('responseText:' + xmlhttp.responseText);
try {
var data = JSON.parse(xmlhttp.responseText);
} catch(err) {
console.log(err.message + " in " + xmlhttp.responseText);
return;
}
on_success(data);
}else{
if(xmlhttp.readyState == 4){
on_error();
}
}
};
xmlhttp.timeout = timeout;
xmlhttp.ontimeout = function () {
on_timeout();
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
return that;
})();
Example:
$ajax.send("someUrl.com", {
onSuccess: function(data){
console.log("success",data);
},
onError: function(){
console.log("Error");
},
onTimeout: function(){
console.log("Timeout");
},
timeout: 10000
});
I appreciate the vanilla js equivalent of a $.getJSON above
but I come to exactly the same point. I actually was trying of getting rid of jquery which I do not master in any way .
What I'm finally strugglin with in BOTH cases is the async nature of the JSON request.
What I'm trying to achieve is to extract a variable from the async call
function shorten(url){
var request = new XMLHttpRequest();
bitly="http://api.bitly.com/v3/shorten?&apiKey=mykey&login=mylogin&longURL=";
request.open('GET', bitly+url, true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
var data = JSON.parse(request.responseText).data.url;
alert ("1:"+data); //alerts fine from within
// return data is helpless
}
};
request.onerror = function() {
// There was a connection error of some sort
return url;
};
request.send();
}
now that the function is defined & works a treat
shorten("anyvalidURL"); // alerts fine from within "1: [bit.ly url]"
but how do I assign the data value (from async call) to be able to use it in my javascript after the function was called
like e.g
document.write("My tiny is : "+data);

AJAX responseXML errors

I've been having some weird issues when it comes to make an AJAX request and handling the response.
I am making an ajax call for an xml file. however when i get the response the xhr.responseText property works fine in firefox but not in IE.
Another thing is that I am trying to access the xhr.responseXML as XMLDocument, but it tells me in firefox it tells me that xhr.responseXML is undefined in ie it doesnt even show me the undefined error or displays the output.
This is the code I am using to make the request:
var ajaxReq = function(url, callback) {
//initialize the xhr object and settings
var xhr = window.ActiveXObject ?
new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(),
//set the successful connection function
httpSuccess = function(xhr) {
try {
// IE error sometimes returns 1223 when it should be 204
// so treat it as success, see XMLHTTPRequest #1450
// this code is taken from the jQuery library with some modification.
return !xhr.status && xhr.status == 0 ||
(xhr.status >= 200 && xhr.status < 300) ||
xhr.status == 304 || xhr.status == 1223;
} catch (e) { }
return false;
};
//making sure the request is created
if (!xhr) {
return 404; // Not Found
}
//setting the function that is going to be called after the request is made
xhr.onreadystatechange = function() {
if (!httpSuccess(xhr)) {
return 503; //Service Unavailable
}
if (xhr.responseXML != null && xhr.responseText != null &&
xhr.responseXML != undefined && xhr.responseText != undefined) {
callback(xhr);
}
};
//open request call
xhr.open('GET', url, true);
//setup the headers
try {
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("Accept", "text/xml, application/xml, text/plain");
} catch ( ex ) {
window.alert('error' + ex.toString());
}
//send the request
try {
xhr.send('');
} catch (e) {
return 400; //bad request
}
return xhr;
};
and this is how i am calling the function to test for results:
window.onload = function() {
ajaxReq('ConferenceRoomSchedules.xml', function(xhr) {
//in firefox this line works fine,
//but in ie it doesnt not even showing an error
window.document.getElementById('schedule').innerHTML = xhr.responseText;
//firefox says ''xhr.responseXML is undefined'.
//and ie doesn't even show error or even alerts it.
window.alert(xhr.reponseXML.documentElement.nodeName);
});
}
This is also my first attempt to work with AJAX so there might be something that I am not looking at right.
I've been searching crazy for any indications of why or how to fix it, but no luck there.
any ideas would be great.
EDIT:
I know this would be better with a framework, but the boss doesn't want to add a framework for just an ajax functionality ('just' is not a fair word for ajax :P). So I am doing it with pure javascript.
The XML file is well-formed, I see it well in the web browser, but for completion this is the testing file I am using:
<?xml version="1.0" encoding="utf-8"?>
<rooms>
<room id="Blue_Room">
<administrator>somebody#department</administrator>
<schedule>
<event>
<requester>
<name>Johnny Bravo</name>
<email>jbravo#department</email>
</requester>
<date>2009/09/03</date>
<start_time>11:00:00 GMT-0600</start_time>
<end_time>12:00:00 GMT-0600</end_time>
</event>
</schedule>
</room>
<room id="Red_Room">
<administrator>somebody#department</administrator>
<schedule>
</schedule>
</room>
<room id="Yellow_Room">
<administrator>somebody#department</administrator>
<schedule>
</schedule>
</room>
</rooms>
EDIT 2:
Well the good news is that I convinced my boss to use jQuery, the bad news is that AJAX still perplexes me. I'll read more about it just for curiousity. Thanks for the tips and I gave the answer credit to Heat Miser because he was the closest working tip.
I was having the same problem a few years ago, then I gave up on responseXML and began always using responseText. This parsing function has always worked for me:
function parseXml(xmlText){
try{
var text = xmlText;
//text = replaceAll(text,"<","<");
//text = replaceAll(text,">",">");
//text = replaceAll(text,""","\"");
//alert(text);
//var myWin = window.open('','win','resize=yes,scrollbars=yes');
//myWin.document.getElementsByTagName('body')[0].innerHTML = text;
if (typeof DOMParser != "undefined") {
// Mozilla, Firefox, and related browsers
var parser=new DOMParser();
var doc=parser.parseFromString(text,"text/xml");
//alert(text);
return doc;
}else if (typeof ActiveXObject != "undefined") {
// Internet Explorer.
var doc = new ActiveXObject("Microsoft.XMLDOM"); // Create an empty document
doc.loadXML(text); // Parse text into it
return doc; // Return it
}else{
// As a last resort, try loading the document from a data: URL
// This is supposed to work in Safari. Thanks to Manos Batsis and
// his Sarissa library (sarissa.sourceforge.net) for this technique.
var url = "data:text/xml;charset=utf-8," + encodeURIComponent(text);
var request = new XMLHttpRequest();
request.open("GET", url, false);
request.send(null);
return request.responseXML;
}
}catch(err){
alert("There was a problem parsing the xml:\n" + err.message);
}
}
With this XMLHttpRequest Object:
// The XMLHttpRequest class object
debug = false;
function Request (url,oFunction,type) {
this.funct = "";
// this.req = "";
this.url = url;
this.oFunction = oFunction;
this.type = type;
this.doXmlhttp = doXmlhttp;
this.loadXMLDoc = loadXMLDoc;
}
function doXmlhttp() {
//var funct = "";
if (this.type == 'text') {
this.funct = this.oFunction + '(req.responseText)';
} else {
this.funct = this.oFunction + '(req.responseXML)';
}
this.loadXMLDoc();
return false;
}
function loadXMLDoc() {
//alert(url);
var functionA = this.funct;
var req;
req = false;
function processReqChange() {
// alert('reqChange is being called');
// only if req shows "loaded"
if (req.readyState == 4) {
// only if "OK"
if (req.status == 200) {
// ...processing statements go here...
eval(functionA);
if(debug){
var debugWin = window.open('','aWindow','width=600,height=600,scrollbars=yes');
debugWin.document.body.innerHTML = req.responseText;
}
} else {
alert("There was a problem retrieving the data:\n" +
req.statusText + '\nstatus: ' + req.status);
if(debug){
var debugWin = window.open('','aWindow','width=600,height=600,scrollbars=yes');
debugWin.document.body.innerHTML = req.responseText;
}
}
}
}
// branch for native XMLHttpRequest object
if(window.XMLHttpRequest) {
try {
req = new XMLHttpRequest();
} catch(e) {
req = false;
}
// branch for IE/Windows ActiveX version
} else if(window.ActiveXObject) {
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
req = false;
}
}
}
if(req) {
req.onreadystatechange = processReqChange;
if(this.url.length > 2000){
var urlSpl = this.url.split('?');
req.open("POST",urlSpl[0],true);
req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
req.send(urlSpl[1]);
} else {
req.open("GET", this.url, true);
req.send("");
}
}
}
function browserSniffer(){
if(navigator.userAgent.toLowerCase().indexOf("msie") != -1){
if(navigator.userAgent.toLowerCase().indexOf("6")){
return 8;
}else{
return 1;
}
}
if(navigator.userAgent.toLowerCase().indexOf("firefox") != -1){
return 2;
}
if(navigator.userAgent.toLowerCase().indexOf("opera") != -1){
return 3;
}
if(navigator.userAgent.toLowerCase().indexOf("safari") != -1){
return 4;
}
return 5;
}
Granted, this is very old code, but it is still working for me on a site I built a few years ago. I agree with everyone else though I typically use a framework nowadays so I don't have to use this code or anything like it anymore.
You can ignore some of the particulars with the split, etc... in the Request onreadystate function. It was supposed to convert the request to a post if it was longer than a certain length, but I just decided it was always better to do a post.
This problem occurs mostly when content type is mis-detected by the browser or it's not sent correctly.
Its easier to just override it:
var request = new XMLHttpRequest();
request.open("GET", url, false);
request.overrideMimeType("text/xml");
request.send(null);
return request.responseXML;
Not sure why... This problem occurs only with Safari and Chrome (WebKit browsers, the server sends the headers correctly).
Are you calling the URL relative to the current document? Since IE would be using the ActiveXObject, it might need an absolute path, for example:
http://some.url/ConferenceRoomSchedules.xml
As for the XML, are you sure it's well-formed? Does it load in an XML editor, for instance?
What I can suggest you is to take a look at frameworks that hide and manage these cross-browser issues for you (in a reliable way). A good point here is jQuery. Doing these things yourself can become quite difficult and complex.
This may be what you need.
//Edit:
This is how the w3school shows it:
function ajaxFunction()
{
var xmlhttp;
if (window.XMLHttpRequest)
{
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
else
{
alert("Your browser does not support XMLHTTP!");
}
}
To avoid your cross browser problems (and save yourself coding a lot of items that a strong community has already developed, tested, and reviewed), you should select a javascript library. JQuery and Dojo are great choices.
I believe that your web server need to serve correct response headers with 'ConferenceRoomSchedules.xml' e.g. Content-Type: text/xml or any other xml type.
The answer provided by Aron in https://stackoverflow.com/a/2081466/657416 is from my point of view the simplest (and the best) one. Here is my working code:
ajax = ajaxRequest();
ajax.overrideMimeType("text/xml");
ajax.open("GET", myurl;

Categories

Resources