Javascript Variable Showing undefined - javascript

I have a global javascript array and i am able to call values from it at the beginning of the function but after that, when i alert leaders[i], it shows as undefined:
It appears the problem occurs when there are two ajax calls nested in each other, JS cannot seem to find the values in the array.
JS
function getLeaders(bool) {
var leaders = new Array();
leaders.push('444');
leaders.push('111');
$.ajax({
url: 'url',
crossDomain: true,
type: 'post',
data: {
'clubID': curClub
},
success: function (data) {
for (var i = 0; i < leaders.length; i++)
{
alert(leaders[i]); <===== working fine here
$.ajax({
url: 'someurl',
crossDomain: true,
type: 'post',
data: {
'id': leaders[i] <====== works here
},
success: function(data3) {
alert(leaders[i]); <======= undefined here
var json3 = jQuery.parseJSON(data3);
}
});
}
}
});
};

Since the call is asynchronous the value of i is more than likely leader.length by the time the call returns. So you are probably accessing an index that is out-of bounds.

Related

Access ajax POST response when in a variable [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
I've built a function to handle a request that I intend to use in various pages. But I can't find a way to access it's return! Here is what my code looks like:
function buscaIdEmpresa() {
var jsonEmail = { "email": emailCurrentUser };
var jsonEmailString = JSON.stringify(jsonEmail);
var test = $.ajax({
url: "https://localhost:44326/test",
type: "post",
async: false,
crossDomain: true,
data: jsonEmailString,
contentType: "application/json",
dataType: "json",
complete: function (data) {
var id = data.responseText;
alert(id)
//this returns id as expected
return id;
}
});
alert(test)
//this returns object Object
return test;
}
function carregaConfigList() {
var id = buscaIdEmpresa()
alert(id)
//this returns object Object
}
Also I am not entirely sure that this is the correct way to tackle the problem. I'm open to suggestions, but I would not like to write the entire ajax function every single time the request needs to be done. How can I access the object value? Is there a more 'correct' way of doing this?
Couple ways you could do this, my preferred method is using async/ await
function buscaIdEmpresa() {
return new Promise(resolve => {
var jsonEmail = { "email": emailCurrentUser };
var jsonEmailString = JSON.stringify(jsonEmail);
$.ajax({
url: "https://localhost:44326/test",
type: "post",
async: false,
crossDomain: true,
data: jsonEmailString,
contentType: "application/json",
dataType: "json",
complete: function (data) {
var id = data.responseText;
resolve(id);
}
});
})
}
async function carregaConfigList() {
var id = await buscaIdEmpresa()
alert(id)
}
But you could also use a callback pattern
function buscaIdEmpresa(callback) {
var jsonEmail = { "email": emailCurrentUser };
var jsonEmailString = JSON.stringify(jsonEmail);
$.ajax({
url: "https://localhost:44326/test",
type: "post",
async: false,
crossDomain: true,
data: jsonEmailString,
contentType: "application/json",
dataType: "json",
complete: function (data) {
var id = data.responseText;
callback(id);
}
});
}
function carregaConfigList() {
buscaIdEmpresa(function(id){
alert(id)
})
}

Javascript - why is this undefined?

The alert at the start shows "undefined", why?
The alerts come in this order:
"success!"
"Data" (what it should be)
"undefined"
I read through multiple threads, the problem was always that ajax was asynchronous, so the data was not defined when it was accessed, but in my case the data is there, the alert in my function shows the data BEFORE the other alert where it is undefined!
Very grateful for any help!
I got this code
var data = getData("");
alert(data); <<<<<<< UNDEFINED
function getData(fileName) {
$.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
var arrData = processData(data);
alert("success!");
alert(arrData); <<<<< WORKS GREAT
return arrData;
},
});
}
function processData(data) {
var arrData = CSVToArray(data);
dimensions = arrData[0];
var objects = [];
objects[0] = dimensions;
for (var i = 1; i < arrData.length; i++){
objects[i] = new Object();
for (var j = 0; j < dimensions.length; j++){
objects[i][dimensions[j]] = arrData[i][j];
}
}
return objects;
}
To clarify, I know asynchronous is the way to go for user experience, but this page just has to show data from this call, so its okay for me to wait for it.
Your getData function doesn't return anything.
You need to return it from the function itself.
function getData(fileName) {
$.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
var arrData = processData(data);
alert("success!");
alert(arrData); <<<<< WORKS GREAT
return arrData;
},
});
}
^ This returns the data within getData. But getData doesn't do anything with it: such as returning it.
function getData(fileName) {
var ourData = "";
$.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
var arrData = processData(data);
ourData = arrData;
},
});
return ourData;
}
This returns the data from getData to whatever calls that function.
edit: also, don't use async:false. Your browser won't capture any events happening until that AJAX completes. The benefit of asynchronous JS is that...we can! And in this case should.
Preface: Don't use async: false. But answering the question:
getData doesn't return anything. You're doing a return from the success callback, but that returns something from the success callback, not getData.
To change it so getData returns something, you'd do this:
function getData(fileName) {
var arrData;
$.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
arrData = processData(data);
},
});
return arrData; // <=== Now `getData` returns something
}
But don't do that. Instead, embrace asynchronous programming and remove async: false. For instance, a callback:
function getData(fileName) {
$.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
callback(processData(data));
},
});
}
...called like this:
getData(function(data) {
alert(data);
});
...or a promise ($.ajax returns one, of sorts):
function getData(fileName) {
return $.ajax({
async:false,
type: "GET",
url: "breastCancer.csv",
dataType: "text",
success: function (data) {
callback(processData(data));
},
}).then(data) {
return processData(data); // <== Becomes the resolution value of `getData`'s promise
});
}
and then
getData().then(function(data) {
alert(data);
});
data is undefined because the function getData doesn't return anything. You should have a look at promises.

Why isn't innerHTML call working?

Link to my codepen:https://codepen.io/Kibitz/pen/PKdLma?editors=1111.
I'm running an ajax call that gets information from Wikipedia for results. Upon succeeding I have a for loop that adds the results to an array.
Currently, I just have one innerHTML statement to try and modify a p tag that starts as the word placeholder.
Eventually, I want to show ten results. Currently, the innerHTML call isn't modifying the placeholder word.
This is a snippet of the ajax call:
$.ajax({
type: "GET",
dataType: 'jsonp',
data: {
format: 'json'
},
cache: false,
url: url,
async: false,
success: function (data) {
for (i = 0; i < 10; i++) {
res[i] = data[1][i];
}
console.log(res);
document.getElementById("results1").innerHTML = res[0];
},
error: function (errorMessage) {
console.log('here');
alert("error");
},
complete: function () {
console.log("complete");
}
});
Could you replace line
document.getElementById("results1").innerHTML =res[0];
with
document.getElementById("result1").innerHTML =res[0];

ajax loading 2 XML documents in order without async:false

I am loading 2 XML documents that both run functions on success, although the function for the 2nd XML document is dependant on the 1st being complete.
If I have async:true:
1st XML
function XmlDataTypes() {
var result = null;
var scriptUrl = "http://domain.com/xml/test.XmlDataTypes?AccountId=" + AccountId;
$.ajax(
{
url: scriptUrl,
type: 'get',
dataType: 'xml',
async: true,
success: function (data) {
//create array to be used in second XML
for (var i = 0; i < xmlRows.length; i++) {
var dataType = xmlRows[i];
var dataTypeId = nodeValue(dataType.getElementsByTagName("DataTypeId")[0]);
var dataTypeName = nodeValue(dataType.getElementsByTagName("DataTypeName")[0]);
dataTypeArray.push({ dataTypeId: dataTypeId, dataTypeName: dataTypeName, position: i, markerArray: [] });
}
},
error: function onXmlError() {
alert("An Error has occurred.");
}
});
return result;
}
2nd XML
function XmlAmenityData() {
var result = null;
var scriptUrl = "http://domain.com/xml/test.XmlAmenityData?AccountId=" + AccountId;
$.ajax(
{
url: scriptUrl,
type: 'get',
dataType: 'xml',
async: true,
success: function (data) {
//store this info in markerArray in dataTypeArray
},
error: function onXmlError() {
alert("An Error has occurred.");
}
});
return result;
}
The XML data can loaded in a random order so the function for the second document will error if the 1st hasn't completed.
If I set:
async: false
It works correctly but I get a warning:
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.
Is there a way around this without using:
async: false
Since the 2nd xml is dependent on the 1st, you can define a callback on success.
Also since ajax is async, you must assign the result when the callback is called. You can define a variable ourside of your function (in this case an array) and put the data there.
var result = [];
function XmlDataTypes(url, accountId, callback) {
var scriptUrl = url + accountId;
$.ajax({
url: scriptUrl,
type: 'get',
dataType: 'xml',
async: true,
success: function (data) {
// do something
result.push(data);
if(typeof callback == 'function') {
callback();
}
},
error: function onXmlError() {
alert("An Error has occurred.");
}
});
}
function doSomething() {
// Do something to store this info in markerArray in dataTypeArray
// XmlAmenityData is in results var.
}
And you can use it like so
var _callback = XmlDataTypes("http://domain.com/xml/test.XmlAmenityData?AccountId=", "1234", doSomething);
XmlDataTypes("http://domain.com/xml/test.XmlDataTypes?AccountId=", "1234", _callback);
EDIT: Updated script based on given scenario.
You could try to return the $.ajax as a promise:
function XmlDataTypes() {
// note domain.com was changes to example.com - this should be changed back
var scriptUrl = "http://example.com/xml/test.XmlDataTypes?AccountId=" + AccountId;
return $.ajax(
{
url: scriptUrl,
type: 'get',
dataType: 'xml',
async: true,
success: function (data) {
//create array to be used in second XML
for (var i = 0; i < xmlRows.length; i++) {
var dataType = xmlRows[i];
var dataTypeId = nodeValue(dataType.getElementsByTagName("DataTypeId")[0]);
var dataTypeName = nodeValue(dataType.getElementsByTagName("DataTypeName")[0]);
dataTypeArray.push({ dataTypeId: dataTypeId, dataTypeName: dataTypeName, position: i, markerArray: [] });
}
},
error: function onXmlError() {
alert("An Error has occurred.");
}
});
}
Then calling them in sequence :
XmlDataTypes.done(XmlAmenityData);
Here is some more documentation :
http://www.htmlgoodies.com/beyond/javascript/making-promises-with-jquery-deferred.html

Function result array inside $.ajax is converted to string

I need to pass array of ids with $.ajax data variable. The array is a result of a function. If i declare this function outside $.ajax it sends array correctly. But if i put same function code inside $.ajax (which is preffered for me), i get it as a string.
function mySort(){ // Do not pass hidden clones
var items = [];
$('#fp_parameters_list').children().each(function(){
if ($(this).is(':visible')) {
items.push($(this).attr('data-parameter-id'));
}
});
return items;
}
// This gives correct ordering
$.ajax({
url: '/echo/json/',
type: 'post',
dataType: 'json',
data: {
ordering: mySort()
}
});
// This gives ordering as a string
$.ajax({
url: '/echo/json/',
type: 'post',
dataType: 'json',
data: {
ordering: function(){ // Do not pass hidden clones
var items = [];
$('#fp_parameters_list').children().each(function(){
if ($(this).is(':visible')) {
items.push($(this).attr('data-parameter-id'));
}
});
return items;
}
}
});
Here's fiddle: http://jsfiddle.net/vxLrN/7/
You can see that first request is sent with ordering as an array, while second pass ordering as string, although, functions are absolutely equal.
How can i put function inline and still get array result?
Thanks
Well make sure that you invoke this anonymous function in order to assign the proper result (array of strings) to the ordering parameter:
data: {
ordering: (function () { // Do not pass hidden clones
var items = [];
$('#fp_parameters_list').children().each(function() {
if ($(this).is(':visible')) {
items.push($(this).attr('data-parameter-id'));
}
});
return items;
})(); // <!-- Here call the anonymous function to get its result
}
Just use $.map to build the array directly instead
$.ajax({
url: '/echo/json/',
type: 'post',
dataType: 'json',
data: {
ordering: $.map($('#fp_parameters_list').children(':visible'), function(el) {
return $(el).data('parameter-id');
})
}
});

Categories