I'm doing an ajax call to a php query that I know returns results. However, I'm getting an empty set ("[]"). Here's my code:
var source = [];
// Get the user data to build the sources
function getUsers() {
var data = $.ajax( {
url: '/s/calendar_userdata.php',
method: 'GET',
dataType: 'json',
success: function(userData) {
console.log(userData); // returns []
var len = userData.length;
for(var i = 0; i < len; i++)
{
source[i] = '/s/events.php?e=' + userData[i]; // error "Uncaught TypeError: Cannot set property '0' of undefined"
}
return source;
}
});
}
I've done a lot of reading of StackOverflow and several tutorials on ajax calls and callbacks specifically. However, I'm stuck. Can someone show me what I've got wrong? I've been on this topic for the past 10 hours and am no longer making progress. Thanks.
Are you sure that's returning a body?
Maybe you could first do a
curl -i {host}:/s/calendar_userdata.php
and post it as an edit.
Also, you could also get the status in the ajax call so you can assure you are not throwing useful information such as a 404 (NOT FOUND).
function getUsers() {
var data = $.ajax( {
url: '/s/calendar_userdata.php',
method: 'GET',
success: function(userData, status) {
console.log('userData: ' + userData + ', status:' + status); // returns []
var len = userData.length;
for(var i = 0; i < len; i++)
{
source[i] = '/s/events.php?e=' + userData[i]; // error "Uncaught TypeError: Cannot set property '0' of undefined"
}
return source;
}
});
Related
I'm using jquery.csv.min.js to create an array based on a csv. This part works fine. However, when I try and parse that 2d array into sessionStorage items, I'm getting the dreaded "Uncaught TypeError: Cannot read property '0' of undefined". Here's what I have so far:
var stationData;
var station = "";
// Gather data from CSVs
$.ajax({
type: "GET",
url: "document.csv",
dataType: "text",
success: function(response){
stationData = $.csv.toArrays(response);
console.log(stationData); // This works and confirms the array in the console
console.log("Station Variables Success!");
}
});
// Parse array into sessionStorage items
$(document).ready(function() {
setTimeout(() => {
station = getUrlParameter('stn');
var v;
var varLen = stationData[0].length;
for(v = 0; v < varLen; v++) {
sessionStorage.setItem(stationData[0][v], stationData[station][v]); // Line producing error
console.log("Setting sessionStorage:" + stationData[0][v] + " to \"" + stationData[station][v] + "\"");
}}, 2000);
});
When I run this on my local XAMPP Apache server, I was getting the same TypeError until I included the setTimeout() to space it out a bit figuring it was trying to set the storage items before the array could finish loading and it worked. Just a 10ms timeout is enough to run it on my local server, which is why it's there. However, when I try and upload this to our live server, the TypeError comes back. I've tried increasing the timeout in increments upto 10000ms but it's still happening. I've googled around with no luck, so I'm hoping someone here might be able to share some insight!
It's throwing TypeError because you are trying to read the value of an asynchronous operation before its returned by the server.
Increasing the timeout is not the option.
You just need to slightly refactor your code like this -
$(document).ready(function() {
function fetchCSVFromServer(successCb, errorCb) {
return $.ajax({
type: "GET",
url: "document.csv",
dataType: "text"
})
.done(successCb)
.fail(errorCb);
}
var successCb = function(response){
// Parse array into sessionStorage items
var stationData = $.csv.toArrays(response);
console.log(stationData); // This works and confirms the array in the console
console.log("Station Variables Success!");
setTimeout(() => {
var station = getUrlParameter('stn');
var varLen = stationData[0].length;
for(let v = 0; v < varLen; v++) {
sessionStorage.setItem(stationData[0][v], stationData[station][v]); // Line producing error
console.log("Setting sessionStorage:" + stationData[0][v] + " to \"" + stationData[station][v] + "\"");
}
}, 2000);
};
var errorCb = function(jqXHR, textStatus, errorThrown) {
console.error(jqXHR);
};
fetchCSVFromServer(successCb, errorCb);
});
This code has 2 parts to it, first making the XHR using the $.ajax in the fetchCSVFromServer function and the second synchronizing the code flow which follows the asynchronous XHR call which is written in the successCb callback.
The trick is to synchronize the callback to run only after the server has sent its response in the .done callback.
This is a well known and a solved problem, for more details refer this question.
On load of my page I execute this function
function getConnection() {
$.ajax({
type: "GET",
url: "../webservice/anonymous_PS.asmx/Get",
data: { "PSname": "LISTE_CONNEXTION" },
async : false ,
success: function (response) {
var data = response.getElementsByTagName("NewDataSet")[0]
for (let i = 0; i < data.children.length; i++) {
var c1Nb = $(data.children[i]).find('c1').text()
var c2Nb = $(data.children[i]).find('c2').text()
var c1 = document.getElementById("cs" + c1Nb)
var c2 = document.getElementById("cs" + c2Nb)
var line = $("#l_" + c1Nb + "_" + c2Nb)
}
}
})
}
But when I do that I have this error on Firefox :
XML Parsing Error: not well-formed
Location:
Line Number 1, Column 131:
and on chrome sometimes I have this error :
devtools was disconnected from the page
How can I resolve my issue ?
Try parsing your response, you can use $.parseXML(response) if you want to parse your response to xml or $.parseHTML(response) if you want to parse your response to html.
Once the parsing is done then your getElementsByTagName("NewDataSet")[0] will work and you will not get any error.
The final code will look something like:
var parsedResponse = $.parseXML(response);
var data = parsedResponse.getElementsByTagName("NewDataSet")[0];
I have done an ajax request in my code and it works good. After that I want to extract only the necessary info and re-post it to another script. Until now here is my code:
$.ajax({
type: "POST",
url: url,
data: {xhr_id: xhr_id},
success: function (jsondata) {
var product_data = [];
for (var i = 0; i <= 3; i++) {
//alert(jsondata.products[i].product_description.toSource());
product_data[i] = {};
product_data[i]["product" + i] = jsondata.products[i].product_description;
//alert(product_data[i]["product" + i].toSource());
}
},
dataType: "json"
});
The problem is that both the alerts work fine, displaying the information I want. However, I get an error message of "Uncaught TypeError: Cannot read property 'product_description' of undefined" which breaks the script and prevents me from doing anything else. What am I doing wrong, any ideas?
'product_description' of undefined" what it means is that your are trying to access property on undefined variable. That implies "jsondata.products[i]" resulted in undefined value which have occured due to index out of range.How many records are returned in jsondata 3 or 4,check and adjust the condition in for loop
The parameter in the success() function of $.ajax is a string. You have to put it through a parse function to make json. See your code below modified but not tested.
$.ajax({
type: "POST",
url: url,
data: {xhr_id: xhr_id},
success: function (jsondata) {
var oData;
try { oData=jQuery.parseJSON(jsondata) }
catch(err) {
alert("Problem parsing json string : " + jsondata)
return false
}
var product_data = [];
for (var i = 0; i <= 3; i++) {
//alert(oData.products[i].product_description.toSource());
product_data[i] = {};
product_data[i]["product" + i] = oData.products[i].product_description;
//alert(product_data[i]["product" + i].toSource());
}
},
dataType: "json"
});
I have searched throughout SO about this issue, but I'm not getting any results in my code.
I have a simple JSON parser here, which creates a table based on a JSON object returned by an endpoint. Here is what I have tried so far.
function getAJAXData(APIurl){
$.ajax({
url: APIurl,
type: "GET",
dataType: "json"
}).then(function(data){
alert(data);
});
}
function generateTable(tableId){
var objRecords = getAJAXData("http://jsonplaceholder.typicode.com/posts");
var cols = addTableHeaders(objRecords, tableId);
for(var i = 0; i < objRecords.length; i++){
var tRow = $('<tr/>');
for (var colIdx = 0; colIdx < cols.length ; colIdx++){
var cellVal = objRecords[i][cols[colIdx]];
cellVal = (cellVal == null) ? "" : cellVal;
tRow.append($('<td/>').html(cellVal));
}
$(tableId).append(tRow);
}
}
function addTableHeaders(myList, tableId){
var colSet = [];
var headers = $('<tr/>');
for (var i = 0; i < myList.length; i++) {
var hRow = myList[i];
for(var key in hRow){
if($.inArray(key, colSet) == -1){
colSet.push(key);
headers.append( $('<th/>').html(key) );
}
}
}
$(tableId).append(headers);
return colSet;
}
That one doesn't work but when I hard-code a list, it generates a table from the hard-coded list. Can someone please explain what I am doing wrong or missing in the code? Thanks .
These two lines are an issue:
var objRecords = getAJAXData("http://jsonplaceholder.typicode.com/posts");
var cols = addTableHeaders(objRecords, tableId);
First off, your getAJAXData function doesn't return anything, so objRecords will always be undefined.
Second, even if it did return something, it's an asyncronous call, so the data won't be ready right away.
What you need to do is to wrap up the relevant bits of your code into a function and call it on the success callback so it gets executed only after your AJAX data is ready.
You need to call addTableHeaders inside of ajax success
$.ajax({
url: APIurl,
type: "GET",
dataType: "json",
success: function(data){
//call it here
}
})
});
If someone could help me with this it would be a life saver!!
(I'm using PARSE)
Basically what this parse job attempts to do is
1) queries all objects of a class called channel
2) loop through each object in the "Results" array which is returned from the query
3) make a call to a Google API which returns a JSON string
4) parse the JSON and save new instances of an Object called Videos
The problem is i keep getting the errors:
Failed with: Uncaught SyntaxError: Unexpected token T in :1
Failed with: Uncaught SyntaxError: Unexpected end of input in :0
Parse.Cloud.job("TestFunction", function(request, status) {
var query = new Parse.Query("Channel");
query.find ({
success: function (results) {
var httpRaw;
for (var i = 0; i < results.length; i++) {
var channel_id = results[i].get("channel_id");
Parse.Cloud.httpRequest({
url: 'https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCKy1dAqELo0zrOtPkf0eTMw&maxResults=50&order=viewCount&type=video&key=AIzaSyCLGCJOPU8VVj7daoh5HwXZASnmGoc4ylo',
success: function (httpResponse) {
httpRaw = httpResponse.text;
},
error: function (httpResponse) {
console.error('Request failed with response code ' + httpResponse.status);
}
});
var json = JSON.parse(httpRaw);
for (var z = 0; z < json.items.length ; z++){
var video = new Parse.Object("Video");
video.set("video_id", json.items[z].id.videoId.toString());
video.set("video_title", json.items[z].snippet.title.toString());
video.set("video_description", json.items[z].snippet.description.toString());
video.set("video_thumbnail", json.items[z].snippet.thumbnails.medium.url.toString());
video.set("date_published", json.items[z].snippet.publishedAt.toString());
var relation = video.relation("parent_channel");
relation.add(results[i]);
video.save();
}
}
},
error: function() {
}
});
});
I'm guessing the cause is JSON.parse(). HTTP requests are non-blocking in cloud code (and generally everywhere in JavaScript) so the JSON.parse() is evaluated before httpRaw has been set.
At a minimum, you need to move the parse() call and the following loop into the success handler of your HTTP request so they wait until you have a valid response. I'd suggest using Promises instead of the success/error callbacks as well.
Here's how I would go about it (warning: untested code follows ...)
Parse.Cloud.job("TestFunction", function(request, status) {
var query = new Parse.Query("Channel");
query.find().then(function(results) {
var requests = [];
for (var i = 0; i < results.length; i++) {
var channel_id = results[i].get("channel_id");
requests.push(Parse.Cloud.httpRequest({
url: 'https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCKy1dAqELo0zrOtPkf0eTMw&maxResults=50&order=viewCount&type=video&key=AIzaSyCLGCJOPU8VVj7daoh5HwXZASnmGoc4ylo'
}));
}
return Parse.Promise.when(requests);
}).then(function(results) {
var videos = [];
for(var i = 0; i < results.length; i++) {
var httpRaw = results[i].text;
var json = JSON.parse(httpRaw);
for (var z = 0; z < json.items.length ; z++){
var video = new Parse.Object("Video");
video.set("video_id", json.items[z].id.videoId.toString());
video.set("video_title", json.items[z].snippet.title.toString());
video.set("video_description", json.items[z].snippet.description.toString());
video.set("video_thumbnail", json.items[z].snippet.thumbnails.medium.url.toString());
video.set("date_published", json.items[z].snippet.publishedAt.toString());
var relation = video.relation("parent_channel");
relation.add(results[i]);
videos.push(video);
}
}
return Parse.Object.saveAll(videos);
});
});