Return a value with jQuery each() function - javascript

i'm new to javascript, and I would like to retrieve values from JSON and push it into an array so that I can parse again this array in another function, But I don't know how to return the array after pushing element inside it.
In the following script I can't display values in items
function gC(b,c,p) {
$.getJSON('getmonths', 'b='+b+'&c='+c+'&p='+p, processJSON);
}
function processJSON(data) {
var retval = [];
$.each(data, function(key, val) {
retval.push(val);
//alert(retval.pop());
});
return retval;
}
$(document).ready(function(){
var b = $("#b").val();
var c = $("#c").val();
var p = $("#p").val();
var items = [];
items = gC(b,c,p);
var i = 0;
$('td').each(function(index) {
$(this).attr('bgcolor', items[i]);
i++;
}
How could I access the array ?
thank !

You don't return from an AJAX call, you have it call a callback function when it's done.
function gC(b,c,p) {
var retval = [];
$.getJSON('getmonths', 'b='+b+'&c='+c+'&p='+p, processData);
}
function processData(data){
var retval = [];
$.each(data, function(key, val) {
retval.push(val);
//alert(retval.pop());
});
alert(retval);
}
processData would be called when the AJAX call is done. This can't return a value to another function, so all your logic has to be inside this callback function.
UPDATE: You can also pass in a callback function to gC to be called when it's done.
function gC(b,c,p,f) {
var retval = [];
$.getJSON('getmonths', 'b='+b+'&c='+c+'&p='+p, function(d){
if(typeof f == 'function'){
f(d);
}
});
}
Then you call gC like so:
gC(b,c,p,function(data){
var retval = [];
$.each(data, function(key, val) {
retval.push(val);
//alert(retval.pop());
});
alert(retval);
});
UPDATE2: I saw the code you added to the question. This needs to be done in the callback.
gC(b,c,p,function(data){
var items = [];
$.each(data, function(key, val) {
items.push(val);
});
$('td').each(function(index){ // You don't need a separate i variable
// you can just use the index from the loop
$(this).attr('bgcolor', items[index]);
}
})

Just have the code inside the callback:
function processJSON(data) {
var retval = [];
$.each(data, function(key, val) {
retval.push(val);
});
$('td').each(function(index) {
if (index < retval.length)
$(this).attr('bgcolor', retval[index]);
});
}

Related

Returning the array before the function is complete & Angular JS

I am trying to return the array 'self.results' with all the arrays pushed in, which is after the self.yelpResults is completed. I want to use the returned array in another function. For now, self.parsedYelpArray is suppose to accept that array.
I am having trouble getting the self.results return all the arrays that are being pushed in. Instead, it asynchronously push the original empty array into the self.parsedYelpArray function.
How do I resolve this?
This is the code in my controller:
self.MapRouteArray = CompileMapArray.compileRoutes(data);
self.yelpResults = CompileYelpResults.compileYelp(self.MapRouteArray);
self.parsedYelpArray = ParsingYelpResults.parsingData(self.yelpResults);
And, these are the relevant services:
.service('CompileMapArray', function () {
var self = this;
self.MapRouteArray = [];
self.compileRoutes = function (data) {
for (var i = 0; i < data.response.route[0].leg[0].maneuver.length; i += 2) {
self.MapRouteArray.push(data.response.route[0].leg[0].maneuver[i].position.latitude + ',' + data.response.route[0].leg[0].maneuver[i].position.longitude);
}
return self.MapRouteArray;
};
})
.service('CompileYelpResults', function (YelpResource) {
var self = this;
self.results = [];
self.compileYelp = function (mapArray) {
for (var j = 0; j < mapArray.length; j++) {
YelpResource.getListings({term: self.yelpSearch, ll: mapArray[0]}, function (response) {
self.results.push(response.businesses);
console.log(self.results);
});
}
return self.results;
};
})
.service('ParsingYelpResults', function () {
var self = this;
self.parsingData = function (results) {
console.log(results);
};
});
You are trying to return from an asynchronous function; you'll always get unreliable results from that, you need to pass in a callback function that handles whatever operation you want at the end of your async... Like:
.service('CompileYelpResults', function (YelpResource) {
var self = this;
self.results = [];
self.compileYelp = function (mapArray, callbackFn) {
for (var j = 0; j < mapArray.length; j++) {
YelpResource.getListings({term: self.yelpSearch, ll: mapArray[0]}, function (response) {
self.results.push(response.businesses);
console.log(self.results);
});
}
callbackFn(self.results);
};
});
Then call the function with a callback function like so:
var parsed = CompileYelpResults.compileYelp(self.MapRouteArray, function(result) {
console.log(result);
});
This goes for all your asynchronous functions.
Relating to your comment the callback function you pass as second parameter to compileYelp takes the place of parsingData, so whatever processing you want to do with the results will be in the body of the callback function. It gives extra advantage in that you can use the results whichever way you like. For example.
var logged = CompileYelpResults.compileYelp(self.MapRouteArray, function(result) {
console.log(result);
});
var stringified = CompileYelpResults.compileYelp(self.MapRouteArray, function(result) {
JSON.stringify(result);
});

JavaScript: Subsititute ForEach and callback in anonymous function

function to_json(workbook) {
var result = {};
workbook.SheetNames.forEach(function(sheetName) {
var roa = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
if(roa.length > 0){
result[sheetName] = roa;
}
});
return result;
}
I have above code. How to alter it, in order to let the anonymous function run only over the first element in SheetNames? (or alternatively alter sth else in order to achieve the same result).
I got this so far, I am not sure it is correct.
...snip
var tmpArray = workbook.SheetNames.slice(0);
tmpArray.forEach(function(sheetName) {
...snip
One way is what you've mentioned, but .slice(0) returns the whole array, so use .slice(0,1) for only the first item:
var tmpArray = workbook.SheetNames.slice(0, 1);
tmpArray.forEach(function(sheetName) { /* ... */ })
But if you only want to process the first item you can cancel the forEach() and the anonymous()
totally:
function to_json(workbook) {
var result = {},
sheetName = workbook.SheetNames[0],
roa = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
if(roa.length > 0) result[sheetName] = roa;
return result;
}

Why can't I access JS object properties?

I have the following function:
function getAggregateData(){
var sums = new Object();
$.getJSON("example.json.php", function(data) {
//for each month
c = 0;
$.each(data, function(key, val, index) {
//for each store
$.each(val, function(key2, val2, index2) {
if(c == 0){
sums[key2] = val2;
}
else{
sums[key2] += val2;
}
});
c++
});
})
return sums;
}
Which I then call as such:
var totals = getAggregateData();
But when I console log I am totally stumped:
console.log(totals)
reveals an object like this:
store1 500
store2 900
store3 750
and so on and so forth...
but when I do console.log(totals['store1') I get undefinded.
I have also tried console.log(totals.store1)
and console.log(totals[0].store1)
I am having some type of issue of scope, or I am not creating the object I think I am.
It looks like the function would be returning an empty object since it's not waiting for the AJAX call to finish.
If you tried doing console.log(totals.store1) on the last line inside your $.getJSON callback you'll probably get a result.
You'll need to put any code that requires data from "example.json.php" inside a callback that only gets run after the AJAX call has returned.
E.g.
function getAggregateData(){
var sums = new Object();
$.getJSON("example.json.php", function(data) {
//for each month
c = 0;
$.each(data, function(key, val, index) {
//for each store
$.each(val, function(key2, val2, index2) {
if(c == 0){
sums[key2] = val2;
}
else{
sums[key2] += val2;
}
});
c++
});
processAggregateData(sums);
})
}
function processAggregateData(totals) {
console.log(totals.store1);
}
getAggregateData();
given:
{
"1": {
"store1": 2450,
"store2": 1060,
"store3": 310
},
"2": {
"store1": 2460,
"store2": 1760,
"store3": 810
}
};
This should work if you intend to add the results for each store.
/**
* This functions need to be called when we have the data
*/
function processSums(obj){
console.log(obj);
}
function getAggregateData(){
var sums = {};
$.getJSON("example.json.php", function(data) {
$.each(data, function() {
$.each(this, function(key, val, index){
sums[key] = sums[key] || 0;
sums[key] += val;
});
});
// 4910
processSums(sums);
});
return sums;
}
getAggregateData();

javascript keys and objects

I have a javascript code below:
function init() {
var data_pie = [];
var data_key = [];
data_pie.push(10,12,30,40,80,25);
data_key.push("x1","x2","x3","x4","x5","x6");
g.update(data_pie, data_key);
}
update: function(data, key) {
var i=-1;
var streakerDataAdded = d3.range(data.length).map(function() {
i++;
return {
name: key[i],
totalPlayers: data[i]
}
});
}
How can I optimize my code to use this object:
var data='{"data":[{"x1":"10","x2":"12","x3":"30","x4":"40","x5":"80","x6":"25"}]}';
Instead data_pie and data_key arrays?
Without being able to test this (not having any access to the rest of your code), you might try something like:
function init() {
var data='{"data":[{"x1":"10","x2":"12","x3":"30","x4":"40","x5":"80","x6":"25"}]}';
for(key in data.data[0]){
g.update(data.data[0][key], key, data.data[0].length);
}
}
update: function(data, key, length) {
var streakerDataAdded = d3.range(length).map(function() {
return {
name: key,
totalPlayers: data
}
});
}
It is very unclear as to why you would use such a data structure but anyway, here we go:
var jsonData = '{"data":[{"x1":"10","x2":"12","x3":"30","x4":"40","x5":"80","x6":"25"}]}';
// var cleanerJsonData = '{"x1":"10","x2":"12","x3":"30","x4":"40","x5":"80","x6":"25"}';
function update(json){
var data = JSON.parse(json).data[0]; // why use an array here?
// var data = JSON.parse(json) - using cleanerJsonData.
var streakerDataAdded = d3.map(data).entries().map(function(d){
return {name: d.key, totalPlayers: d.value} })
}
}

encapsulation issue with making an array of objects

Would anyone mind explaining to me why...
$(document).ready(function() {
var scu = ['0291285', '0409338', '0521704', '0521990', '0523652', '0523657', '0523660', '0523704'];
var inData = $('#output');
var testdiv = $('#testdiv');
function Item(scu, description, price, extended, type) {
this.scu = scu;
this.description = description;
this.price = price;
this.extended = extended;
this.type = type;
//this.saved = function() {};
}
var rows = [];
function get() {
inData.html('');
$.each(scu, function(index, val) {
$.post('chBuild.php', {scu:val}, function(output) {
$.each(output, function(i, obj) {
var i = 0;
rows[i] = new Item(obj.scu, obj.description, obj.price, obj.extended, obj.type);
console.log(rows[i].price)
//this logs every object but...
i =+ 1;
});
}, 'json');
});
console.log(rows[0].price);
//this says rows[0] is undefined?
}
inData.click(get);
});
I am trying to find the best way to create and store multiple objects.
$.post('chBuild.php', {scu:val}, function(output) {
$.each(output, function(i, obj) {
var i = 0;
rows[i] = new Item(obj.scu, obj.description, obj.price, obj.extended, obj.type);
console.log(rows[i].price)
i =+ 1;
});
}, 'json');
Here the call to $.post is asynchronous, is going to be filled just when the ajax call returns. Maybe you should make it synchronous
$.ajax({'url': 'chBuild.php', 'async': false, ...);
It's because $.post is asynchronous. The each only start the HTTP request, but it returns immediatly, so when the second console.log runs the item had not been created yet.

Categories

Resources