Parse Queries through Nested For Loops is Giving Duplication of Results - javascript

I'm attempting to loop through an array to query my order class to find an associated id, then loop through
another class with that id.
There are 4 elements in the origin array, and they should match to an id each of which have 43 elements in the 3rd query.
However instead of getting 43 results from the 3rd query per id, I'm getting 12*43 results.
I can't figure out how my code is wrong and I've tried containedIn also without any results.
$scope.positionIds = [];
$scope.dataDictionary = {};
$scope.quotes = function () {
for (var i=0; i < $scope.positions.length; i++){
var positionNow = $scope.positions[i];
var orderQuery = new Parse.Query('Order');
orderQuery.equalTo('objectId', positionNow );
orderQuery.find({
success: function(result) {
console.log(result);
for (var j=0; j < result.length; j++){
$scope.positionIds.push(result[j].attributes.positionId);
}
for (var k=0; k < $scope.positionIds.length; k++){
var portfolioQuery = new Parse.Query('DayPosition');
portfolioQuery.limit(1000);
var positionSecond = $scope.positionIds[k];
portfolioQuery.equalTo('positionId', positionSecond);
console.log("positionId", $scope.positionIds[k]);
portfolioQuery.find({
success: function(result) {
console.log("count", result.length);
for (var h=0; h < result.length; h++){
// console.log("count", result.length);
console.log("double inside data time", result[h].createdAt);
console.log("double inside data id", $scope.positionIds[k]);
console.log("value", result[h].attributes.currentValue);
var values = [];
values.push([result[h].createdAt,
result[h].attributes.currentValue]);
if (!$scope.dataDictionary[result[h].attributes.positionId]){
$scope.dataDictionary[result[h].attributes.positionId] = [];
} else {
$scope.dataDictionary[result[h].attributes.positionId].push(values);
}
}
console.log("final data", $scope.dataDictionary);
},
error: function (error) {
console.log("this error", error);
}
});
}
},
error: function (error) {
console.log("this error", error);
}
});
}
};

Related

Deferred objects with multiple getJSON calls that depend on each other

I am making 3 get JSON calls in myFunction() that gets called on a button click. 2 of these getJSONs depend on each other for their execution. It basically parses through 10 web pages and collects some data. With this data it will go to another page and collect some other data. I want to display "DONE" at the end of myFunction so the user knows that we have finally got all data and the search operation is complete. However these calls, I think, are asynchronous, so I use deferred objects. But even though I pass all calls to $.when.apply(call1,call2,call3), it displays the "DONE" before any data is printed on the console. Once it prints "DONE", then it starts to print the results. How can I modify my code so that I would be able to display "DONE" only when myFunction has ran completely for all 10 pages and has printed all data on the console.
var call1 = [];
var call2 = [];
var call3 = [];
function myFunction() {
data3 = [];
url = ''; // some URL here
call3.push($.getJSON(url, function(data4) {
data3 = data4;
}));
for (var page = 1; page < 10; page++) {
(function(page) {
url = 'http://example.com/' + page;
call1.push($.getJSON(url, function(data1) {
for (var num = 0; num < data1.standings.results.length; num++) {
(function(num) {
url = 'http://example.com/' + data1.entry[num];
call2.push($.getJSON(url, function(data2) {
for (var i = 0; i < 15; i++) {
(function(i) {
console.log(data3.ele[(data2.p[i].element) - 1].x);
return;
}
})(i);
}
})
);
})(num);
}
})
);
})(page);
};
$.when.apply(call1, call2, call3).then(function() {
console.log("DONE");
});
}
I was finally able to solve this problem. As mentioned in the comments, we need to chain various promises and the function structure should match the structure of the when command. So, in the function as call1 was pushed first, I need to call the when command for call1 and then nest the subsequent commands and so on.
var call1 = [];
var call2 = [];
var call3 = [];
function myFunction() {
data3 = [];
url = ''; // some URL here
call3.push($.getJSON(url, function(data4) {
data3 = data4;
}));
for (var page = 1; page < 10; page++) {
(function(page) {
url = 'http://example.com/' + page;
call1.push($.getJSON(url, function(data1) {
for (var num = 0; num < data1.standings.results.length; num++) {
(function(num) {
url = 'http://example.com/' + data1.entry[num];
call2.push($.getJSON(url, function(data2) {
for (var i = 0; i < 15; i++) {
(function(i) {
console.log(data3.ele[(data2.p[i].element) - 1].x);
return;
}
})(i);
}
})
);
})(num);
}
})
);
})(page);
};
$.when.apply($, call1).then(function(){
$.when.apply($, call2).then(function(){
document.getElementsByName('output')[0].value+="Search Completed"+'\r\n';
});
});
}

Check against two arrays using for loop and if statement

I'm trying to run a check against two arrays (one has 4 objects, one just have a few strings) with for loops and if statement for a problem set.
The idea is to use for loop to iterate over every element in the object array and the string array, then use if statement to figure out matches and shove the matching string into a new array. Once all the elements are iterated, it returns the string if there is a matching one.
The problem is the function calls it a day once a single match in the object array is found and returns that only that instead of iterating over the rest of the elements in the object array.
var passengers = [
{ name: ["Michael Jackson"], paid: true },
{ name: ["Osama"], paid: false },
{ name: ["Harambe"], paid: true },
{ name: ["Pepe"], paid: true },
];
var noFlyList = ["Jimmy", "John", "Pepe", "Osama"];
function checkNoFly(passengers, noFlyList) {
for (var i = 0; i < passengers.length; i++) {
for (var j = 0; j < noFlyList.length; j++) {
if (passengers[i].name[0] == noFlyList[j]) {
var passengerList = [];
passengerList.push(passengers[i].name[0]);
return passengerList;
}
}
}
return true;
}
function checkNotPaid(passengers) {
return (!passengers.paid);
}
function processPassenger(passengers, testFunction) {
for (var i = 0; i < passengers.length; i++) {
if (testFunction(passengers[i])) {
return false;
}
}
return true;
}
var allCanFly = processPassenger(passengers, checkNoFly);
if (!allCanFly) {
console.log("We cannot fly because " + checkNoFly(passengers, noFlyList) + " is on the no-fly list");
}
var allPaid = processPassenger(passengers, checkNotPaid);
if (!allPaid) {
console.log("we cannot fly because not all passengers have paid");
}
use this: having passengerList in the loop make its reinitialized to empty array on each loop, and returning passengerList in the loop makes the loop break once it finishes the first loop
function checkNoFly(passengers, noFlyList) {
var passengerList = [];
for (var i = 0; i < passengers.length; i++) {
for (var j = 0; j < noFlyList.length; j++) {
if (passengers[i].name[0] == noFlyList[j]) {
passengerList.push(passengers[i].name[0]);
}
}
}
return passengerList;
}
EDIT:
change your original processPassenger function to the one below, originally you have only 1 argument passed to your checkNoFly function, where you'd defined it to take 2 arguments, so the false is returned for wrong number of argument, which stop you from getting it the way you want.
function processPassenger(passengers, testFunction) {
if (testFunction(passengers, noFlyList).length !=0) {
return false;
}
return true;
}
EDIT 2: for your updated question, since for the first check we are returning an array for the single function processPassenger() for validation, we can take similar approach for the checkNotPaid function to return an array for those who have not paid.
function checkNotPaid(passengers) {
var passengerNotPaid = [];
for (var i = 0; i < passengers.length; i++) {
if (!passengers[i].paid) {
passengerNotPaid.push(passengers[i].name[0]);
}
}
return passengerNotPaid;
}
unless you'd want to refactor everything, i think this would be ok.
You're telling it to do so: return passengerList; in your inner loop. Also, you keep re-declaring the variable var passengerList = []; inside your inner for-loop, emptying it every time.
var passengers = [
{ name: ["Michael Jackson"], paid: true },
{ name: ["Osama"], paid: false },
{ name: ["Harambe"], paid: true },
{ name: ["Pepe"], paid: true },
];
var noFlyList = ["Jimmy", "John", "Pepe", "Osama"];
function checkNoFly(passengers, noFlyList) {
var passengerList = [];
for (var i = 0; i < passengers.length; i++) {
for (var j = 0; j < noFlyList.length; j++) {
if (passengers[i].name[0] == noFlyList[j]) {
passengerList.push(passengers[i].name[0]);
}
}
}
return passengerList;
}
function checkNoPay(passengers) {
var nonPayers = [];
for (var i = 0; i < passengers.length; i++) {
if (!passengers[i].paid) { nonPayers.push(passengers[i].name); }
}
return nonPayers;
}
var banList = checkNoFly(passengers, noFlyList);
if (banList.length) {
console.log("We cannot fly because " + banList + " is/are on the no-fly list");
}
var unpaidList = checkNoPay(passengers);
if (unpaidList.length) {
console.log("We cannot fly because " + unpaidList + " has/have not payed the flight");
}
var canWeFly = !(banList.length || unpaidList.length);
console.log(canWeFly ? "We can fly" : "We cannot fly");

JavaScript Json row undefined for TreeView

I have a question. When querying my Json object, although i have my Field as same name and all Json rows available give me an error that is undefined.
//e.g: row.DepParentId
Bellow is my code. Am I missing some tag?
function convert(rows) {
debugger;
function exists(rows, parent) {
for (var i = 0; i < rows.length; i++) {
if (rows[i].DepId === parent) return true;
}
return false;
}
var nodes = [];
// get the top level nodes
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
if (!exists(rows, row.DepParentId)) {
nodes.push({
id: row.DepId,
name: row.Title
});
}
}
var toDo = [];
for (var i = 0; i < nodes.length; i++) {
toDo.push(nodes[i]);
}
while (toDo.length) {
var node = toDo.shift();
// the parent node
// get the children nodes
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
if (row.DepParentId == node.Id) {
var child = {
Id: row.DepId,
Name: row.Title
};
if (node.options) {
node.options.push(child);
} else {
node.options = [child];
}
toDo.push(child);
}
}
}
return nodes;
}
My Json example for one row picked from Firefox
"{"DepId":7,"DepParentId":3,"Title":"OTT"}"
Thanks for helping
Joao
thanks all for helping, it's working now, the problem was the JSON.stringify() was returning only an [Object] so when you use JSON.parse() generates a sintax error.
function onLoaded() {
var itemsCount = items.get_count();
for (var i = 0; i < itemsCount; i++) {
var item = items.itemAt(i);
var dep = JSON.stringify(item.get_fieldValues());
deps.push(dep);
}
So, i had to change the format to be valid to parse like this
var dt = "[" + deps + "]";
var ret = JSON.parse(dt);
Thanks
Joao

Value won't push to array

In the code below, I assign a value to a variable from JSON with this var tag = data[j]['text']; and I output it with this console.log(tag); (for testing) which works.
I try to push the values into an array with tags.push(tag); but it WILL NOT WORK!
Why won't these values go into the array? I am just trying to get the contents of tag into an array...
function GetAvailableTags() {
var url = '/TextCodes/TextCodes?key=';
var tagGroups = [];
$('.ui-autocomplete-input').each(function () {
var key = $(this).attr('id');
var tags = [];
//console.log(key);
$.getJSON(url + key, function (data) {
for (var j = 0, len = data.length; j < len; j++) {
var tag = data[j]['text'];
console.log(tag);
tags.push(tag);
}
});
console.log(tags.length);
for (var k = 0, len = tags.length; k < len; k++) {
console.log(tags[k]);
}
});
}
Thanks for your help.
Because $.getJSON is an asynchronous function. It means that your code
console.log(tags.length);
for (var k = 0, len = tags.length; k < len; k++) {
console.log(tags[k]);
}
will be executed before the $.getJSON callback function :
function () {
var key = $(this).attr('id');
var tags = [];
//console.log(key);
$.getJSON(url + key, function (data) {
for (var j = 0, len = data.length; j < len; j++) {
var tag = data[j]['text'];
console.log(tag);
tags.push(tag);
}
}
It is why your variable seems to be empty when look into in your code above, but how it is possible that the data are printed with console.log(tag); in the callback function.
Update
Here is an example of using $.ajax method instead of $.getJSON to specify that the data must be retrieved synchronously using the parameter asynch : false
By that way, the server call response (success callback) is mandatory to continue the process. The disadvantage of this non-standard way is that your web page could be freezed waiting the server response. It is not the best elegant way to do that, but sometimes it is useful.
function GetAvailableTags() {
var url = '/TextCodes/TextCodes?key=';
var tagGroups = [];
$('.ui-autocomplete-input').each(function () {
var key = $(this).attr('id');
var tags = [];
//console.log(key);
$.ajax({
url: url + key,
type: 'POST',
asynch: false,//specify to stop JS execution waiting the server response
success: function (data) {
for (var j = 0, len = data.length; j < len; j++) {
var tag = data[j]['text'];
console.log(tag);
tags.push(tag);
}
},
error : function(jqXHR, textStatus, errorThrown) {
alert('an error occurred!');
}
});
console.log(tags.length);
for (var k = 0, len = tags.length; k < len; k++) {
console.log(tags[k]);
}
});
}
My solution is kind of long and stupid, but it works. Now, I can access the variables like an array textCodes['taxes']. sdespont's async note helped, too.
var textCodes = GenerateTextCodes();
console.log(textCodes);
function GenerateTextCodes() {
var arr = [];
$('.ui-autocomplete-input').each(function () {
var id = $(this).attr('id');
arr[id] = GetAvailableTags(id);
});
//console.log(arr['taxes']);
return arr;
}
// get all autocomplete element IDs and put them into an array
function GetAvailableTags(key) {
var url = '/TextCodes/TextCodes?key=';
var tags = [];
$.ajax({
url: url + key,
type: 'GET',
async: false,
success: function (data) {
//console.log(data[0].text);
//console.log(data.length);
for (var i = 0; i < data.length; i++) {
//console.log(data[i].text);
tags.push(data[i].text);
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert('an error occurred!');
}
});
//console.log(tags);
return tags;
}

Unexpected behaviors with closure function scope

I am fairly certain this is a ten penny closure question. But having read a few articles on closures, I still cannot get this to work.
character is always returned as 'Z'. character is also a global variable.
I need "render" to remember the character in the loop:
populateList: function()
{
var render = function(tx, result)
{
console.log(character);
for (var i = 0; i < result.rows.length; i++)
{
var contact = result.rows.item(i);
console.log(contact.Name);
}
}
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for(var i = 0; i < str.length; i++)
{
var nextChar = str.charAt(i);
database.open();
var sql = "SELECT Name FROM Contact WHERE Name LIKE \'" + nextChar + "%\' ORDER BY Name";
database.query(sql, render);
}
}
var render = function(character)
{
return function(tx, result)
{
console.log(character);
for (var i = 0; i < result.rows.length; i++)
{
var contact = result.rows.item(i);
console.log(contact.Name);
}
}
}
Usage:
database.query(sql, render(nextChar));
Edit:
Also, asawyer is correct in his comment above -- assuming you are using node-mysql, it has support for parameterized queries:
database.query("SELECT * FROM foo WHERE bar = ?", [ 1 ]);
Use that and save yourself some trouble!
Untested:
populateList: function()
{
var render = function(char)
{
console.log(char);
return function(tx, result) {
for (var i = 0; i < result.rows.length; i++)
{
var contact = result.rows.item(i);
console.log(contact.Name);
}
};
}
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for(var i = 0; i < str.length; i++)
{
var nextChar = str.charAt(i);
database.open();
var sql = "SELECT Name FROM Contact WHERE Name LIKE \'" + nextChar + "%\' ORDER BY Name";
database.query(sql, render(nextChar));
}
}
Use an immediately executing function that returns a function that calls render with the parameters:
database.query(sql, (function(nextChar) {
return function(tx, result) {
return render(tx, result, nextChar);
};
})(nextChar));
Then add the appropriate nextChar parameter to render, too.
var render = function(tx, result)
{
console.log(character);
***var char = character;***
for (var i = 0; i < result.rows.length; i++)
{
var contact = result.rows.item(i);
***console.log(char);***
console.log(contact.Name);
}
}
i guess this is what you need. add the highlighted lines. cheers

Categories

Resources