I have a piece of code in an app that I am having difficulty pushing items to an empty array. At the beginning of this section, I created some empty array variables.
var sumPOP = [];
var sumRACE = [];
var sumLANG = [];
var sumINCOME = [];
I am going to then iterate through some selected data, so I have a for loop. Within this loop, I am making a call to an api (I know, it's GIS. That's irrelevant. Just pretend it's an ajax call) to retrieve some data. I am able to console.log() the data and it shows up correctly. I then want to push that data (each item in the loop) to the before mentioned empty arrays. Then to test that the array has been populated, I console.log() the array, both within the loop and outside it. My problem is that nothing shows when I console.log the array. Why is the data not getting pushed outside the array? Note: console.log(sumPOP) run within the call function(esriRequest) does show the items pushed to the array:
for (var i=0;i<results.features.length;i++){
...
esriRequest({
url:"https://api.census.gov/data/2016/acs/acs5",
content:{
get: 'NAME,B01003_001E,B02001_001E,B06007_001E,B06010_001E',
for: `tract:${ACS_TRCT}`,
in: [`state:${ACS_ST}`,`county:${ACS_CNTY}`]
},
handleAs:'json',
timeout:15000
}).then(function(resp){
result = resp[1];
POP = result[1];
console.log(POP);
sumPOP.push(POP);
RACE = result[2];
LANG = result[3];
INCOME = result[4];
console.log('POP: ' + POP + ', RACE: ' + RACE + ', LANG: '+ LANG + ', INCOME: ' + INCOME);
}, function(error){
alert("Data failed" + error.message);
});
console.log('POP: ' + sumPOP);
...
}
console.log('POP: ' + sumPOP);
Additional information: My eventual goal is to get the final array after the selected data has been iterated through and summarize it; or rather, add it together. My expected array results would be sumPOP = [143, 0, 29, 546, 99];
I want apply a function (also outside the loop) to do this:
newSum = function(category) {
let nAn = n => isNaN(n) ? 0 : n; //control for nonNumbers
return category.reduce((a, b) => nAn(a) + nAn(b))
};
...and then run popTotal = newSum(sumPOP); to get the total.
I believe your data is being pushed, it just appears that it isn't due to the placement of your console.log()'s
Since you are dealing with an async api call, the only place where you are guaranteed to have data is inside your .then() function. Essentially, as you debug, if you add breakpoints, at all your console.log's, you will notice that it hits the ones outside the .then() first and the ones inside the .then() last. Because of that ordering, it will appear that your arrays did not get data pushed to them.
I added some comments to your example code below to illustrate where you should expect to see data.
EDIT: also I made a small adjustment so all the arrays would get populated
EDIT 2: modified the code so it handles multiple async promises in a "synchronous" manner
var sumPOP = [];
var sumRACE = [];
var sumLANG = [];
var sumINCOME = [];
var myPromises = []; // added this new array for promise.all
for (var i = 0; i < results.features.length; i++) {
var myPromise = esriRequest({
url: "https://api.census.gov/data/2016/acs/acs5",
content: {
get: 'NAME,B01003_001E,B02001_001E,B06007_001E,B06010_001E',
for: `tract:${ACS_TRCT}`,
in: [`state:${ACS_ST}`, `county:${ACS_CNTY}`]
},
handleAs: 'json',
timeout: 15000
});
myPromises.push(myPromise);
// because you are making an async request, at this point, sumPOP may be empty
console.log('POP: ' + sumPOP);
}
Promise.all(myPromises).then(function(resp) {
result = resp[1];
POP = result[1];
console.log(POP); // this will show POP with data
RACE = result[2];
LANG = result[3];
INCOME = result[4];
sumPOP.push(POP);
sumRACE.push(RACE); // added this to populate array
sumLANG.push(LANG); // added this to populate array
sumINCOME.push(INCOME); // added this to populate array
// at this point, all your arrays should have data
console.log('POP: ' + POP + ', RACE: ' + RACE + ', LANG: ' + LANG + ', INCOME: ' + INCOME);
// now that this you have all values, you can call your outside function
this.handleData();
}, function(error) {
alert("Data failed" + error.message);
});
// because you are making an async request, at this point, sumPOP may be empty
console.log('POP: ' + sumPOP);
var handleData = function() {
// do something with the completed data
}
Related
Steps to reproduce:
1: Visit https://www.chess.com/play/computer
2: Paste JS code in the console
Expected results:
Pieces are printed by their square number ascendingly
Actual results:
Uncaught TypeError: newPieces.sort is not a function error is thrown
JS code:
pieces = ["r","n","b","q","k","p"];
colors = ["w","b"];
squareTemplate = "square-";
boardTemplate = "chess-board.layout-board";
function updatePieces(){
return document.querySelectorAll("chess-board.layout-board .piece");
}
function getFen(isFlipped){
}
function evalMove(){
}
console.log("Starting up ...");
const board = document.querySelector(boardTemplate);
let newPieces = [];
newPieces = updatePieces();
newPieces.sort(function(a,b){return a.classList[2].split('-')[1] - b.classList[2].split('-')[1]});
let fenRows = [];
for(i=0;i<newPieces.length;i++){
let classList = newPieces[i].classList;
let pieceColor = classList[1][0];
let pieceType = classList[1][1];
let pieceSquare = classList[2].split('-')[1];
//console.log(" Piece color is: " + pieceColor + " it is: " + pieceType + " and it is in: " + pieceSquare);
if(pieceColor == 'w'){
pieceType.toUpperCase();
} else {
pieceType.toLowerCase();
}
fen
}
So, basically JS is trying to tell me that is not an array, well, if it is not an array, then I am born in Bangladesh, because it is let newPieces = [];
updatePieces function in not returning an array, and sort method only work on array's, please first check updatePieces() function output
sort() is a method located on the Array.prototype which is what you want to use where as querySelectorAll() returns a static NodeList representing a list of the document's elements that match the specified group of selectors not an array. this is why your getting your exception. if you wish to use sort, you need to convert it into an array.
You can convert it to an array using array.from
const pieces = document.querySelectorAll("chess-board.layout-board .piece");
const arr = Array.from(pieces);
I have a table in my mysql db with columns id and drivers_license_number. Now data in drivers_license_number column is stored in plaintext, and I want to encrypt it.
This table contains about 400000 records. I have read about problems with LIMIT and OFFSET issue and try to use in my query late row lookups.
So first of all I need to get data from db, then encrypt the right field and update db with this encrypted field. I don't understand, how to organize my code to send parameters with limit and offset to db. I need to work in loop in this situation?
function getUpdatedEncryptedField(db_table_name, field_name) {
return getDataFromDb(db_table_name, field_name).then(function(result){
return encryptData(result, field_name).then(function (result){
var promises = result.map(function(item) {
var data = [item[field_name], item.id];
return updateFieldNameData(db_table_name, field_name, data);
});
return q.all(promises);
});
});
}
After the first pass I will get for example first 1000 records and how to move forward to get another 1000 rows?
function getDataFromDb(db_table_name, field_name, limit, offset) {
var sql = 'SELECT ds.id, ' + field_name + ' FROM ( SELECT id FROM ' + db_table_name + 'WHERE ' + field_name +
' IS NOT NULL ORDER BY id LIMIT ' + limit + ', ' + offset + ') d JOIN ' + db_table_name + ' ds ON ds.id = d.id ORDER BY ds.id;'
return db.modio.executeSql(sql);
}
You can use a carring/high order function to update the chunks by e.g 1000 and get the next 1000 records until the 400000, like so:
function getUpdatedEncryptedField(db_table_name, field_name) {
var idFrom = 0;
var idTo = 1;
return function getDataFromDB(db_table_name, field_name){
idFrom = idTo;
idTo += 1000;
console.log(id range is ${idFrom}-${idTo}`);
// call your db to get the recods
}
}
// assign high order func to updateChunks var, which is again a func
var updateChunks = getUpdatedEncryptedField('studentsDB','creditCard')
// so each time you execute updateChunks() the values idFrom & idTo are updated
// updateChunks()
// id range is 1-1001
// updateChunks()
// id range is 1001-2001
// and so on
// create a loop until you get all the table records, e.g.
// pay attention to define 'i' with let and not with var because of async loop
for(let i=0; i <= 400000/1000; i++){
// call the updateChunk func here
// at eaach itteration it will ask for the next chunk of records
updateChunks()
}
`
Of course you should update a little bit your mysql query, to get the range of Ids from - to, this is out of the question scope.
Hope helps, good luck.
So I am trying to get a list of clients from an array and then display them one by one into a context menu sub menu. But somehow I am confused on how to do it. Any help would be really appreciated.
So below is the code that I have already tried but I am always getting the last item from the list like this, while I would like to get all the items from the list one under the other.
action: function () {
var itemDisp = [];
var client;
var arrayLength = clients_array.length;
for (var i = 0; i < arrayLength; i++) {
client = clients_array[i].toString().split(',');
displayClient.push(client[0] + ' - ' + client[1]);
clientDisp = client[0] + ' - ' + client[1];
itemDisp = { label: displayClient[i]};
}
}
return {
"AddClient" : {
label: "Add Client",
"submenu": {
itemDisp
}
}
}
Right now I am getting the last item from the array with the above code, while I would like to get all the items found in the array.
It looks like you need an array. However in your code you are overwriting the array with an object. This might explain why you only see the last object.
Instead try this:
function () {
var itemDisp = [];
var client;
var arrayLength = clients_array.length;
for (var i = 0; i < arrayLength; i++) {
client = clients_array[i].toString().split(',');
displayClient.push(client[0] + ' - ' + client[1]);
clientDisp = client[0] + ' - ' + client[1];
// Important part here!
itemDisp.push({ label: displayClient[i]});
}
}
return {
"AddClient" : {
label: "Add Client",
// Also changed. We just pass the array.
"submenu": itemDisp
}
}
By using the array push method we add the object to the end of the itemDisp array.
I'm new to Firebase, and I'm going to build a list of item collected from server with following criterias:
max 10 items
order by item value (eg. 'count')
this is my code
FBRef.orderByChild("count").limitToLast(10).on("child_added", function(snapshot){}
and it worked fine, but when a new record inserted, is there a Firebase method that can check and auto update the list if the new item is in top 10 ? Or I need to to it myself ?
var FBRef = new Firebase('yours.firebaseio.com');
FBRef.orderByChild("count").limitToLast(5).on("child_added", function(snapshot){
var data = snapshot.val();
var html = "<li>value: " + data.value + " - count: " + data.count + "</li>";
$("#result").prepend(html);
});
$(document).ready(function () {
$("#inputaddbtn").click(add);
});
function add(){
var value = $("#inputvalue").val();
var count = $("#inputcount").val();
$("#inputcount").val("");
$("#inputvalue").val("");
FBRef.push({
value : value,
count : count
})
}
You'll need to monitor more events and handle more arguments to keep the list limited.
As a first step: Firebase will fire a child_removed event when an element has been removed from the location or (in your case) falls outside of the query.
You can handle that event to remove the child from the list:
var FBRef = new Firebase('yours.firebaseio.com');
var query = FBRef.orderByChild("count").limitToLast(5);
query.on("child_added", function(snapshot){
var data = snapshot.val();
var html = "<li id='key_"+snapshot.key()+"'>value: " + data.value + " - count: " + data.count + "</li>";
$("#result").prepend(html);
});
query.on("child_removed", function(snapshot){
$('#key_'+snapshot.key()).remove();
});
You'll note that I give the li an id when the child is added and then remove the li based on that id when Firebase tells me to.
This covers simple adding/removing items. For a complete app that handles all cases, you should also handle child_changed and child_moved. And you'll probably also want to handle the second argument to the callbacks, which indicates the key of the item that the child needs to go after. But maybe your use-case doesn't require handling these cases, in which case the above is enough.
I am inserting some data into an array but I am getting
,9,My firstname,My lastname,myemail#example.com,123456789
out in my console. How can I remove comma from first element i.e. 9? here is my code
var data = new Array();
$(row_el.children("td")).each(function(i) {
var td = $(this);
//var data = td.html();
var td_el = td.attr('class');
//arr[i] = data;
if(!td.hasClass("element")) {
data[i] = td.html();
console.log(i + ": " + data);
}
});
I want output like this
9,My firstname,My lastname,myemail#example.com,123456789
then I will pass this array to a function and loop through this array.
Just use push() (MDN docu) instead of setting to a specific position inside your array:
var data = new Array();
$(row_el.children("td")).each(function(i) {
var td = $(this);
//var data = td.html();
var td_el = td.attr('class');
//arr[i] = data;
if(!td.hasClass("element")) {
data.push( td.html() );
console.log(i + ": " + data);
}
});
The problem is, that not all the elements in the array processed by each() result in an entry in your array. However, the index submitted to your callback (i) counts upwards nonetheless. So if there are some elements, that do not result in an entry to your array, these positions are filled with undefined (as long as you enter an element at a later position). These undefined entries now result in an empty string when outputting it the way you do, thus resulting to your leading comma.