$.getJSON with for loop, just working when debugging - javascript

**I really need help, because I´m not able to find a working solution or do it by my self. The problem is, that I can´t get the information. "data" should include 23 objects. The thing is, while debugging everything works well. Please help me!!! I am nearly on my end. and Callback or then.(function...) are not working for me... ;( **
function query_day2day(DateArray_){
var Fluid_id = 0;
var data_list = new Array();
//read out the select element
var e = document.getElementById("select_fluid");
var Fluid_id = e.options[e.selectedIndex].value;
//read in date
//var d = document.getElementById("datepicker");
//var date = d.value;
var dateArray = new Array();
dateArray = DateArray_;
//Bring the date array in the correct form to submit
for(i = 0; i<dateArray.length; i++)
{
var year = dateArray[i].substring(6, 10); //substring(start, end)
var month = dateArray[i].substring(0, 2);
var day = dateArray[i].substring(3, 5);
dateArray[i] = year + "-" + month + "-" + day;
//alert(dateArray[i]);
}
for(i = 0; i<dateArray.length; i++)
{
switch (Fluid_id) {
case '1':
$.getJSON(setAddress_Event() + 'liter_hour/' + Fluid_id + '/' + dateArray[i], function(data){
//data_callback(data, i); //I don´t understand this concept ;(
data_list[i] = data;
});
break;
case '2':
$.getJSON
Updated
function getData(setAddress_Event, liter_hour, Fluid_id, dateArray){
return $.getJSON(setAddress_Event + liter_hour + Fluid_id + "/" + dateArray).then(function(data){
return {
data_list:data
}
});
}
for(var j = 0; j<dateArray.length; j++)
{
getData(setAddress_Event(), "liter_hour/", Fluid_id, dateArray[j]).then(function(returndata){
//received data!
alert(j);
data_collection[j] = returndata;
});
}
alert(data_collection); //Hier ist data_list undefined und beim returnen wird es richtig übergeben.... ohne diesem alert wird falsch übergeben.... dreck
return data_collection;
Please help me, I need all data not just the last one. Debugging works, I don´t know what´s here the problem....
Debugg Snippet

This is because you are accessing the data before the Ajax requests for retrieving the JSON have sent back the responses. Be aware that when you execute
getData(setAddress_Event(), "liter_hour/", Fluid_id, dateArray[j]).then(function(returndata){
//received data!
alert(j);
data_collection[j] = returndata;
});
... the inner function is not executed. It is only passed on to getData, and your code continues immediately. Only when the execution reached the end of the script, will the Ajax requests one by one call your callback function, so they all execute after the main scripts ends.
Here is how you could deal with that (introducing a variable numPendingResults):
var numPendingResults = dateArray.length;
for(let j = 0; j<dateArray.length; j++) {
getData(setAddress_Event(), "liter_hour/", Fluid_id,
dateArray[j]).then(function(returndata){
//received data!
data_collection[j] = returndata;
numPendingResults--; // one less to wait for!
if (!numPendingResults) { // we have everything!
console.log(data_collection);
// anything you want to do with data_collection should be done here
// ...
// or call a function that will deal with it, from here.
}
});
}
You cannot return the data_collection. Instead you should call a function like described above. Possibly that function can be passed as argument by the outermost function. Or use the Promise system one step further. For you to decide...

Try something similar to this. You may need to loop through the elements in order to use them.
$.getJSON('/ReferenceData/PhoneType',
function (data) {
if (!isBound) {
dropDownToBind.append($('<option></option>').val(-1).html('- Select Type -'));
$.each(data, function (index, element) {
dropDownToBind.append($('<option></option>').val(element['Id']).html(element['Value']));
});
isBound = true;
}
});
// OR this
$.getJSON(url, params, function (data) {
if (data != null) {
zip_code_field.closest('.formCol').find('.ZipCity').val(data.City);
zip_code_field.closest('.formCol').find('.ZipState').val(data.State);
$.uniform.update();
}
});

Related

Insert Logging In Functions ASP.NET

I have an .ascx containing javascript and div elements.
I want insert a log statement inside a function for troubleshooting.
May I know how can I achieve it?
Below is my code snippet:
function SaveGroupCheck() {
var isValid = true;
var haveError = false;
var schedule = document.getElementById("<%=ddlExecutionSchedule.ClientID%>").value;
//INSERT LOGGING HERE - Value of 'schedule'//
if (schedule == "Weekly")
{
var xday = document.getElementById("<%=chkSelectDay.ClientID%>");
var checkbox = xday.getElementsByTagName("input");
var counter = 0;
for (var i = 0; i < checkbox.length; i++) {
if (checkbox[i].checked) {
counter++;
}
}
//INSERT LOGGING HERE - Value of 'counter'//
if (counter < 1) {
$("#chkSelectDay").addClass('errorbox');
$("#divSelectDay").addClass('has-error has-feedback');
$("#lblSelectDay").addClass('has-error has-feedback');
haveError = true;
}
else {
$("#chkSelectDay").removeClass('errorbox');
$("#divSelectDay").removeClass('has-error has-feedback');
$("#lblSelectDay").removeClass('has-error has-feedback');
}
}
//INSERT LOGGING HERE - Value of 'haveError'//
Below is a log which I attempted but failed. I will use a try-catch if the error info needs to be provided.
var logFileName = ConfigurationManager.AppSettings["logpath"] + "Debug_" + DateTime.Now.ToString("ddMMyyyy_hhmmss") + ".log";
var itemPerPage = document.getElementById("<%=txtItemsPerPage.ClientID%>").value;
Log(DateTime.Now.ToString("ddMMyyyy_hhmmss") + " - itemPerPage = " + itemPerPage);
*logpath configured in app.config.
Thank you for your time.
To log any javascript variables you can use :
console.log("Hello I'm the variable value");
and open chrome console to see the value.
If you want to send variable value to server you must go to ajax call by calling server method for logging.
I hope that I understood your question.

Javascript array shows in console, but i cant access any properties in loops

I really try my damndest not to ask, but i have to at this point before I tear my hair out.
By the time the js interpreter gets to this particular method, I can print it to the console no problem, it is an array of "event" objects. From FireBug I can see it, but when I try to set a loop to do anything with this array its as if it doesn't exist. I am absolutely baffled......
A few things:
I am a newbie, I have tried a for(var index in list) loop, to no avail, I have also tried a regular old for(var i = 0; i < listIn.length; i++), and I also tried to get the size of the local variable by setting var size = listIn.length.
As soon as I try to loop through it I get nothing, but I can access all the objects inside it from the FireBug console no problem. Please help, even just giving me a little hint on where I should be looking would be great.
As for the array itself, I have no problems with getting an array back from PHP in the form of: [{"Event_Id":"9", "Title":"none"}, etc etc ]
Here is my code from my main launcher JavaScript file. I will also post a sample of the JSON data that is returned. I fear that I may be overextending myself by creating a massive object in the first place called content, which is meant to hold properties such as DOM strings, settings, and common methods, but so far everything else is working.
The init() function is called when the body onload is called on the corresponding html page, and during the call to setAllEvents and setEventNavigation I am lost.
And just to add, I am trying to learn JavaScript fundamentals before I ever touch jQuery.
Thanks
var dom, S, M, currentArray, buttonArray, typesArray, topicsArray;
content = {
domElements: {},
settings: {
allContent: {},
urlList: {
allURL: "../PHP/getEventsListView.php",
typesURL: "../PHP/getTypes.php",
topicsURL: "../PHP/getTopics.php"
},
eventObjArray: [],
buttonObjArray: [],
eventTypesArray: [],
eventTopicsArray: []
},
methods: {
allCallBack: function (j) {
S.allContent = JSON.parse(j);
var list = S.allContent;
for (var index in list) {
var event = new Event(list[index]);
S.eventObjArray.push(event);
}
},
topicsCallBack: function(j) {
S.eventTopicsArray = j;
var list = JSON.parse(S.eventTopicsArray);
topicsArray = list;
M.populateTopicsDropDown(list);
},
typesCallBack: function(j) {
S.eventTypesArray = j;
var list = JSON.parse(S.eventTypesArray);
typesArray = list;
M.populateTypesDropDown(list);
},
ajax: function (url, callback) {
getAjax(url, callback);
},
testList: function (listIn) {
// test method
},
setAllEvents: function (listIn) {
// HERE IS THE PROBLEM WITH THIS ARRAY
console.log("shall we?");
for(var index in listIn) {
console.log(listIn[index]);
}
},
getAllEvents: function () {
return currentArray;
},
setAllButtons: function (listIn) {
buttonArray = listIn;
},
getAllButtons: function () {
return buttonArray;
},
setEventNavigation: function(current) {
// SAME ISSUE AS ABOVE
var l = current.length;
//console.log("length " + l);
var counter = 0;
var endIndex = l - 1;
if (current.length < 4) {
switch (l) {
case 2:
var first = current[0];
var second = current[1];
first.setNextEvent(second);
second.setPreviousEvent(first);
break;
case 3:
var first = current[0];
var second = current[1];
var third = current[2];
first.setNextEvent(second);
second.setPreviousEvent(first);
second.setNextEvent(third);
third.setPreviousEvent(second);
break;
default:
break;
}
} else {
// do something
}
},
populateTopicsDropDown: function(listTopics) {
//console.log("inside topics drop");
//console.log(listTopics);
var topicsDropDown = document.getElementById("eventTopicListBox");
for(var index in listTopics) {
var op = document.createElement("option");
op.setAttribute("id", "dd" + index);
op.innerHTML = listTopics[index].Main_Topic;
topicsDropDown.appendChild(op);
}
},
populateTypesDropDown: function(listTypes) {
//console.log("inside types drodown");
//console.log(listTypes);
var typesDropDown = document.getElementById("eventTypeListBox");
for(var index2 in listTypes) {
var op2 = document.createElement("option");
op2.setAttribute("id", "dd2" + index2);
op2.innerHTML = listTypes[index2].Main_Type;
typesDropDown.appendChild(op2);
}
}
},
init: function() {
dom = this.domElements;
S = this.settings;
M = this.methods;
currentArray = S.eventObjArray;
buttonArray = S.buttonObjArray;
topicsArray = S.eventTopicsArray;
typesArray = S.eventTypesArray;
M.ajax(S.urlList.allURL, M.allCallBack);
//var tempList = currentArray;
//console.log("temp array length: " + tempList.length);
M.setAllEvents(currentArray);
M.testList(currentArray);
M.setEventNavigation(currentArray);
//M.setEventNavigation();
M.ajax(S.urlList.topicsURL, M.topicsCallBack);
M.ajax(S.urlList.typesURL, M.typesCallBack);
}
};
The problem you have is that currentArray gets its value asynchronously, which means you are calling setAllEvents too soon. At that moment the allCallBack function has not yet been executed. That happens only after the current running code has completed (until call stack becomes emtpy), and the ajax request triggers the callback.
So you should call setAllEvents and any other code that depends on currentArray only when the Ajax call has completed.
NB: The reason that it works in the console is that by the time you request the value from the console, the ajax call has already returned the response.
Without having looked at the rest of your code, and any other problems that it might have, this solves the issue you have:
init: function() {
dom = this.domElements;
S = this.settings;
M = this.methods;
currentArray = S.eventObjArray;
buttonArray = S.buttonObjArray;
topicsArray = S.eventTopicsArray;
typesArray = S.eventTypesArray;
M.ajax(S.urlList.allURL, function (j) {
// Note that all the rest of the code is moved in this call back
// function, so that it only executes when the Ajax response is
// available:
M.allCallBack(j);
//var tempList = currentArray;
//console.log("temp array length: " + tempList.length);
M.setAllEvents(currentArray);
M.testList(currentArray);
M.setEventNavigation(currentArray);
//M.setEventNavigation();
// Note that you will need to take care with the following asynchronous
// calls as well: their effect is only available when the Ajax
// callback is triggered:
M.ajax(S.urlList.topicsURL, M.topicsCallBack); //
M.ajax(S.urlList.typesURL, M.typesCallBack);
});
}

javascript keeping a var within inner functions

I am making a website based dashboard. one of the functionalities is showing the locations of all customers. when i'm placing these on the map i can't seem to get the pop-up right.
function getCoordinates(locationList) {
for (var i = 0; i < locationList.length; i++) {
if (locationList[i].city != null) {
$http.get('https://api.tiles.mapbox.com/geocoding/v5/mapbox.places/' + locationList[i].city + '.json?access_token=' + access_token)
.success(
function (data) {
var marker = L.marker([data.features[0].center[1], data.features[0].center[0]]).addTo(mymap);
marker.bindPopup(locationList[i].customerName);
}
);
}
}
}
When I use this code the pop-up will only contain the last customer's name in every pop-up.does someone know how to make sure that the attributes of the correct user are used?
That's a closure problem, to fix it you have to move your $http call to a new function like this.
function httpCall(locationList,i){
$http.get('https://api.tiles.mapbox.com/geocoding/v5/mapbox.places/' + locationList[i].city + '.json?access_token=' + access_token)
.success(
function (data) {
var marker = L.marker([data.features[0].center[1], data.features[0].center[0]]).addTo(mymap);
marker.bindPopup(locationList[i].customerName);
}
);
}
After for loop i is always locationList.length - 1. Try to add IIFE with local i. For example you can solve the problem with replacing for loop with locationList.forEach
This is Infamous Loop Problem. Since you are just defining the function and not actually executing it when the for loop ends all the functions will have the same values for index i.
Solution: Is to assign the value to a variable and use this variable inside you success callback.
for (var i = 0; i < locationList.length; i++) {
if (locationList[i].city != null) {
var currLocation = locationList[i]; // assign the data to a variable
$http.get('https://api.tiles.mapbox.com/geocoding/v5/mapbox.places/' + locationList[i].city + '.json?access_token=' + access_token)
.success(
function (data) {
var marker = L.marker([data.features[0].center[1], data.features[0].center[0]]).addTo(mymap);
marker.bindPopup(currLocation.customerName); // use the variable instead of the indexed lookup
}
);
}
}
Let me know if this helps.
It's a scope problem. Your i is updated and later, when you will click on the popup, it will read the last value of i.
You should put your conditional in the for a function which take in parameter the i :
function getCoordinates(locationList) {
for (var i = 0; i < locationList.length; i++) {
conditionalGet(i);
}
function conditionalGet(i) {
if (locationList[i].city != null) {
$http.get('https://api.tiles.mapbox.com/geocoding/v5/mapbox.places/' + locationList[i].city + '.json?access_token=' + access_token)
.success(function (data) {
var marker = L.marker([data.features[0].center[1], data.features[0].center[0]]).addTo(mymap);
marker.bindPopup(locationList[i].customerName);
});
}
}
}

Can't add new name and value to JSON object dynamically with condition using JavaScript

I can't add new name and value ff. this given condition:
$.each(names, function (i, name) {
$.get('https://www.example.com/path/' + name, function (data) {
var arrNow = CSVToArray(data, ',');
allArr.push(arrNow);
counter++;
if (counter === names.length) {
for (var j = 0; j < allArr.length; j++) {
for (var k = 1; k < allArr[j].length; k++) {
//console.log(allArr[j][k][0] + ': ' + allArr[j][k][1]);
//var f = moment(allArr[j][k][0]).format('lll');
var f = allArr[j][k][0];
json.push({
"datetime": f
});
if (j == 0) {
if (json[k].datetime === allArr[0][k][0]) {
var newAtt = "water_actual";
var newValue = allArr[0][k][1];
json[k][newAtt] = newValue;
}
}
if (j == 1) {
if (json[k].datetime === allArr[1][k][0]) {
var newAtt = "rainfall_actual";
var newValue = allArr[1][k][1];
json[k][newAtt] = newValue;
}
}if (j == 2) {
if (json[k].datetime == allArr[2][k][0]) {
var newAtt = "forecast_water";
var newValue = allArr[2][k][1];
json[k][newAtt] = newValue;
}
}
}
}
};
});
});
I was able to add a new namewater_actual and its value using if statement. If the datetime from the json object matches to the array value(date and time), I'd like to add it with its specific name as stated above. But I can't seem to make it work.
Here's the fiddle.
If I may provide some general feedback: it's probably good practice to simplify your code to the minimum example that reproduces your problem. Not only can that drastically increase your chances of fixing it yourself, it also increases the odds that you'll get help here.
With that in mind, consider the basic structure of what you're trying here:
var someNames = ["foo", "bar"];
var allTheData = [{
"aardvark": true
}];
$.each(someNames, function (i, name) {
$.get('http://example.com/api/' + name, function (data) {
data.aNewProperty = 'wombat';
allTheData.push(data);
});
});
console.log(allTheData);
Here, $.each iterates through everything in someNames and then proceeds immediately to the console.log statement. For all we know, each individual API call ($.get) could take seconds, or minutes. By this time we've already tried to use the contents of allTheData, which may or may not have been modified.
To avoid this sort of thing in legacy JavaScript we can make use of the callback already provided by $.get:
$.get('http://example.com/api/' + name, function (data) {
data.aNewProperty = 'wombat';
console.log(data);
});
Inside the callback, we know for sure that the API request has already completed (although the above assumes that it succeeded, which is a whole other kettle of fish). This would output the result of each API request as the responses arrive, though not necessarily in the order you'd expect!
JavaScript's asynchronous nature tended to lead in the past to a whole lot of callbacks. With the advent of ES6 we have some more options available to us, especially promises.

Variable scope or return issue (not sure which)

Using the script below I'm attempting to create an object called temptagarray which gets populated with all the tags on a Tumblr weblog and their frequency. So it should end up looking like this:
{'performance': 10, 'installation': 5}
I know the object is being created and it looks correct (I can print it out in each loop) but I can't figure out how to use it after/outside the function i.e. at the bottom of the script where I attempt to document.write() it out. Is this a global/local variable issue, a return issue or do I need to address it in some way?
<script type="text/javascript">
var temptagarray = {};
var tags;
var tag;
function loadPosts () {
var key = "api_key=9I4rZAYQCbU1o5TSMZuyrlvXiQsNxKBicCJxNK5OKZ6G9pgdim";
var api = "https://api.tumblr.com/v2/blog/garrettlynch.tumblr.com/";
var retrieve_more = function (offset) {
$.getJSON(api + "posts?callback=?&filter=image&limit=20&offset=" + offset + "&" + key,function(data) {
//for each item (post) in the response
$.each(data.response.posts, function(i, item) {
//pull out the posts tags
tags = item['tags'];
//loop through the tags
for (i = 0; i < tags.length; i++)
{
tag = tags[i];
//if the tag already exists in the tag array
if (temptagarray[tag])
{
temptagarray[tag] = temptagarray[tag] + 1;
}
else
{
temptagarray[tag] = 1;
}
}
});
if (data.response.posts.length == 20) {
retrieve_more(offset + 20);
}
});
};
retrieve_more(0);
}
loadPosts();
document.write(JSON.stringify(temptagarray));
</script>
Thanks in advance
Garrett
Replace this:
if (data.response.posts.length == 20) {
retrieve_more(offset + 20);
}
...with this:
if (data.response.posts.length == 20) {
retrieve_more(offset + 20);
} else {
document.write(JSON.stringify(temptagarray));
}
The problem you're having is that, despite your document.write(...) command being located below the ajax call in your code, the ajax call is asynchronous and thus the callback will be invoked asynchronously as well. Basically, document.write(...) is being invoked long before you've had a chance to interact with the temptagarray variable in the ajax callback.
First things first - AJAX is Async Asynchronous.
So the code block does not wait for the previous instruction to be completed before it executes the next line.
So your document.writeline would have already been executed by the time the response comes back.
Try printing that info in the success call back after the if block and you would indeed see the response.
thanks for the replies. Below is what I have now as a workable solution as the result is going to call another function anyway. Reading a little bit more I'm wondering if I should be using a callback - is it better?
<script type="text/javascript">
//load posts from a Tumblr weblog
function loadPosts () {
//api key and weblog address
var key = "api_key=9I4rZAYQCbU1o5TSMZuyrlvXiQsNxKBicCJxNK5OKZ6G9pgdim";
var api = "https://api.tumblr.com/v2/blog/garrettlynch.tumblr.com/";
//tags object
var temptagarray = {};
//all tags and each tag
var tags;
var tag;
//looping function to keep retrieving posts until all are retrieved
var retrieve_more = function (offset) {
$.getJSON(api + "posts?callback=?&filter=image&limit=20&offset=" + offset + "&" + key,function(data) {
//for each item (post) in the response
$.each(data.response.posts, function(i, item) {
//pull out the posts tags
tags = item['tags'];
//loop through the tags
for (i = 0; i < tags.length; i++)
{
//pull out each tag
tag = tags[i];
//if the tag already exists in the tag array
if (temptagarray[tag])
{
//add 1 to its count
temptagarray[tag] = temptagarray[tag] + 1;
}
else
{
//set its count to 1
temptagarray[tag] = 1;
}
}
//to test object as it gets added to
//$("#Posts ul").append('<li>' + JSON.stringify(item, ['tags']) + '</li>')
});
//if the number of posts is more than 20
if (data.response.posts.length == 20)
{
//retrieve the next 20
retrieve_more(offset + 20);
}
else
{
//call the show result function
showresult(temptagarray);
}
});
};
//stop retrieving posts
retrieve_more(0);
}
loadPosts();
function showresult(tagarray)
{
$("#Posts ul").append('<li>' + JSON.stringify(tagarray) + '</li>');
//document.write(JSON.stringify(tagarray));
}
</script>

Categories

Resources