Javascript, Cannot read property of undefined, but prints to console - javascript

I have a jQuery call which is getting the data in to a object.
I'm trying to use the object value to set as a label text from javascript, but it throws
"Cannot read property '0' of undefined."
where as it prints the value successfully to the console.
var questionData;
var optionData;
$(document).ready(function () {
$.ajax({
url: 'coaching-assessment-tool.aspx/GetCATQuestionAndOptions',
type: 'POST',
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function (data) {
questionData = data.d[0];
optionData = data.d[1];
console.log(questionData[0].QuestionText);
console.log("Question Data", questionData);
console.log("Option Data", optionData);
},
error: function (error) {
console.log(error);
alert('Error retrieving data. Please contact support.');
}
});
document.getElementById('firstQuestion').innerHTML = questionData[0].QuestionText;
});
I need the label text as the object value (questionData[0].QuestionText).

$.ajax() is asynchronous by default, so setting innerHTML is happening before questionData is populated. Move line 22 inside the success callback to make sure the data is available before it is used.
While it's technically possible to make the call synchronous, it's a bad idea.
$.ajax({
// ...
async: false,
// ...
});
That code would prevent any other JavaScript from executing until the ajax call is complete.
Just as an aside, some JavaScript tooling like TypeScript can help you catch those mistakes before the code executes in a browser. I've recently converted some JS to TS and been very happy with the number of bugs I've caught.
Cheers!

Related

Uncaught TypeError: number is not a function when parsing JSONP response in jQuery ajax call

I am trying to grab data from a wordpress blog using the WP-API plugin. My js file is using jQuery to make ajax calls to the api. I need to use JSONP as the response type since I am trying to access cross domain information.
When the page loads, I get an error "Uncaught TypeError: number is not a function" and my response begins like this: /**/1([{"ID":231,"title":blahblahblah... with the error pointing at the "1" in the console.
This is the code I am using to try and grab the data and parse it:
function get_posts(num_offset) {
offset = num_offset,
url = 'http://www.example.com/wp-json/posts?_jsonp=1&filter[posts_per_page]=5&filter[offset]=' + offset;
$.ajax({
type: 'GET',
dataType: "jsonp",
url: url,
success: function (data) {
consol.log(data);
console.log(url);
}
});
// second ajax call to get the total number of posts
$.ajax({
type: 'GET',
dataType: "jsonp",
url: 'http://www.example.com/wp-json/posts?_jsonp=1&filter[offset]=-1',
success: function (data) {
console.log(data);
}
});
}
I guess I need to know how I can remove the "Uncaught TypeError: number is not a function" error and then how I would be able to parse the JSONP data.
much thanks!
You're telling the other end that your callback's name is 1, in your URL:
http://www.example.com/wp-json/posts?_jsonp=1&filter[offset]=-1
Here --------------------------------^^^^^^
You want to use the name of the callback function you have on your page that you're expecting to receive the JSONP response, which needs to be a validate identifier literal (so not 1).
Because you're using jQuery, it's best by far if you let jQuery worry about what the callback name should be, by leaving off that query parameter entirely and letting jQuery add it. Since _jsonp is an unusual query string parameter name for this, you'll need to tell jQuery what the parameter name is.
$.ajax({
type: 'GET',
dataType: "jsonp",
url: 'http://www.example.com/wp-json/posts?&filter[offset]=-1',
// No _jsonp=1 here ------------------------^
jsonp: '_jsonp',
// ^^ new parameter here
success: function (data) {
console.log(data);
}
});

jQuery.ajaxSetup() Is Being Ignored

In a JS file I have this:
$.ajaxSetup({
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: "json",
data: {},
error: function (jqXHR, textStatus, errorThrown) {
debugger;
}
});
Then further on in the file I instantiate an object that has an AJAX call in it's constructor to fill out some values.
function RequestViewModel() {
var self = this;
(...)
// Initalization Methods
$.ajax({
url:ajaxAddress + 'LoadStates',
success: function (data) {
debugger;
}
});
}
var model = new RequestViewModel();
However, when the ajax call is made in the code, 'xml' is being used as the dataType instead of JSON. This is causing my web service call to break and I always get sent to the error callback of the AJAX call. If I move the settings inside the actual AjAX call, the call works and data is returned from the server. For some reason, the global setting isn't being honored.
My question is why isn't this working? I've used this same technique several other times without this problem.
I'm using jQuery version 1.7.1.
UPDATE
It seems like the problem is on line 7517 of the jQuery file. It is doing an IF statement that is being evaulated to false and is skipping over setting the correct Content Type in the request header.
Try putting your .ajaxSetup inside a document ready wrapper.(NOT likely the cause though)
Try using jQuery.ajaxSetup instead of $.ajaxSetup
It is recommended that global event handlers not be in the ajaxSetup. move error: to $.ajaxError( instead:
jQuery.ajaxError( function (e, jqxhr, settings, exception) {
alert(settings.url + " Failed");
});
Example if you have a div with a log class (puts some text in if any error occurs:
$("div.log").ajaxError(function() {
$(this).text( "Triggered ajaxError handler." );
});
NOTE: when you refactor, make sure to remove the LAST comma.
Also, if you are using the latest version of jQuery (1.7.1 at the moment) you can simplify:
contentType: "application/json; charset=utf-8",
to
contentType: "application/json",
EDIT: quick, dirty global handler:
$(document).ajaxError(function(e, xhr, settings, exception) {
alert('error in: ' + settings.url + ' \\n'+'error:\\n' + exception);
});
EDIT2: SOME resources also put an empty data set sent as: (with quotes)
data: "{}",
Where is .ajaxSetup() being called? Are you using any other plugins? It's possible some other library is misbehaving and overwriting your options.

jQuery $.ajax call works in Chrome, but not any other browser

The following call works perfectly in Chrome, but fails in every other browser.
function getInfo(r,c,f){
return $.parseJSON($.ajax({
url: baseURL + 'somethingAPI/getInfo',
data: {
"data_r": r,
"data_c": c,
"data_f": f
},
//success: function(data){},
dataType: "json",
async: FALSE
}).response);
}
Yes, I'm using a synchronous ajax call and I believe it is necessary as I don't want any of the other JS to run without this executing and returning data. Although, I'm not entirely sure if something else should be happening with the success callback.
Anyway, in Chrome I get the response object (JSON) and can access the data within just fine.
Does anyone know what I'm doing wrong?
Regarding your point about not knowing how to avoid async: false, is this something like what you're looking to accomplish?
function getInfo(r, c, f, callback) {
$.ajax({
url: baseURL + 'somethingAPI/getInfo',
data: {
"data_r": r,
"data_c": c,
"data_f": f
},
dataType: "json",
success: callback,
});
}
getInfo('foo', 'bar', 'baz', function(response) {
console.log(response);
});
Rather than parsingJson on the ajax query, here's the syntax I use to conquer these challenges
$.ajax({
url: "pagegoeshere.php",
timeout: 30000,
type: "POST",
data: 'data1='+data1+'&data2='+data2,
dataType: 'json',
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("An error has occurred making the request: " + errorThrown)
},
success: function(returnjson){
var returnstuff = returnjson.returnstuff;
//Do next Javascript step here
}
});
You can run ensuing javascript/jquery in the success and "stack" events together on success of your Ajax call. That way, if it works, it proceeds. Otherwise, the error handling can occur in the provided error section in a manner that you define. I generally fire my ajax calls on a click handler, but it's certainly doable to run it in a function as you have chosen. Be sure to check your return JSON (could be mailed from your processing page, for example) to make sure it's valid JSON. Jsonlint is your friend!
I've had chrome effectively parse bad HTML and JSON while the other browsers don't on several occasions. I'd suspect it's something along those lines that's specifically causing your issues.

Javascript object declaration in IF statement

I'm sorry about the title I'm just not sure how to describe this one.
Basically I'm using JQUERY/ajax to invoke a php script to validate some input and get some data. The returned data is encoded JSON, so i set the datatype to JSON in JQUERY and it returns an object.
I have just discovered that under certain (it has to be said unusual) conditions where a network connection is not responding in an expected way, the ajax call invokes the error option in JQUERY.
In most cases I have an error message coming back from the server, but sometimes the error is reached and no JSON has been sent back from the server side script. I haven't tracked down exactly what can provoke that network situation yet, but in any case I thought I'd just deal with it back in Javascript whilst I don't yet know.
The idea was to check to see if the expected object had been created, and if not then create it with the two expected properties and run a dialogue. This way I'd avoid repeating writing the error messages. It's not a big saving, but I wanted to try the principle.
$.ajax({
url: 'getmetadata.php',
type: "POST",
data: entereddata,
dataType: "json",
timeout: (7000), //wait 7 seconds
error: function(data)
{
// handle errors
if(data)
{
// Do nothing error message will be issued from the data object
}else{
// no message was returned. Some other error occured.
function tempdata()
{
this.errortitle = "Error title";
this.errormessage = "Error text";
};
var data = new tempdata();
};
// issue error message
runDialogue(data.errortitle,data.errormessage);
}, //ERROR
success: function(data)
{
}; // SUCCESS
}); // AJAX
in the code above, the data object should either exist or not before the "if" statement. And when I get to the runDialogue(); the object data should always exist in order to pass the errortitle and errordescription properties.
When the "data" object exists, there is no problem. What isn't working is when the "data" object does not exist, ie if fails the "if" test. The else should create the object "data" but doesn't.
What have i done wrong?
You are redefining the variable data in your else block(more specific scope) and hence the global scope variable will still be undefined.
Change var data = new tempdata(); to
data = new tempdata(); //In the else block
So, now your ajax call should look like:
$.ajax({
url: 'getmetadata.php',
type: "POST",
data: entereddata,
dataType: "json",
timeout: (7000), //wait 7 seconds
error: function(data)
{
// handle errors
if(data)
{
// Do nothing error message will be issued from the data object
}else{
/******************NOTE THE CHANGE HERE********************/
data = {
errortitle:"Error title",
errormessage:"Error text"
};
};
// issue error message
runDialogue(data.errortitle,data.errormessage);
}, //ERROR
success: function(data)
{
}; // SUCCESS
}); // AJAX
Javascript throws an error on undefined references; you can't test existence just using the object. You can use the typeof operator to test whether the data exists, or instead whether it is of type "object".
For example:
if (typeof data === "undefined")
{
// You don't really need a closure for this...
errordata = {'errortitle' : 'Error Title',
'errormessage' : 'Error Message'};
runDialogue(data.errortitle, data.errormessage);
}
When $.ajax fails (because of a HTTP error), the .error method is called and passed the following params:
error(jqXHR, textStatus, errorThrown)
So the first parameter, which you have called "data", is not "what the webserver sent you" but a jquery wrapped xmlhttprequest object. Testing it via "if" [eg if (data)] will always return true.

A quick question on data returned by jquery.ajax() call (EDITED)

EDIT: The original problem was due a stupid syntax mistake somewhere else, whicj I fixed. I have a new problem though, as described below
I have the following jquery.ajax call:
$.ajax({
type: 'GET',
url: servicesUrl + "/" + ID + "/tasks",
dataType: "xml",
success : createTaskListTable
});
The createTaskListTable function is defined as
function createTaskListTable(taskListXml) {
$(taskListXml).find("Task").each(function(){
alert("Found task")
}); // each task
}
Problem is: this doesn't work, I get an error saying taskListXml is not defined. JQuery documentation states that the success functions gets passed three arguments, the first of which is the data.
How can I pass the data returned by .ajax() to my function with a variable name of my own choosing.
My problem now is that I'm getting the XML from a previous ajax call! How is this even possible? That previous function is defined as function convertServiceXmlDataToTable(xml), so they don't use the same variable name.
Utterly confused. Is this some caching issue? If so, how can I clear the browser cache to get rid of the earlier XML?
Thanks!
See my comment. If you're using IE, GET AJAX requests are cached. jQuery can solve this for you by adding a random querystring variable to the request. Simply change your AJAX call to this:
$.ajax({
type: 'GET',
url: servicesUrl + "/" + ID + "/tasks",
cache: false,
dataType: "xml",
success : createTaskListTable
});
That will add the random querystring automatically, thus preventing the browser from caching the request.
Try defining your callback inline like this:
success: function createTaskListTable(data, textStatus, xhr) {
console.dir(data, textStatus, xhr);
}
If data is indeed being returned as null, you might get some insight from the other fields, especially xhr.
Note that error callbacks get called with (xhr, textStatus, errorThrown).

Categories

Resources