Why is angular extend function not combining two json objects - angularjs

I have JavaScript vars so that I can view what is going on underneath the hood, so to say.
The first two vars are displaying their respective objects just fine, but not the third, which is using angular.extend to combine two json objects retrieved from two different databases. One is a local db and the other is from a production db.
The common id between the two json is what I am trying to "merge"
JSON 1:
[{"ID": 1, "TITLE": "CSR", "PHONE": "555-555-1212", "FNAME": "JOHN", "LNAME": "SMITH"}]
JSON 2:
[{"ID": 1, "GROUP_MEMBER_ID": "1","GROUP_MEMBER_TYPE_ID":"4","GROUP_ID":"1"}]
The result that I would like to see:
[{"ID": 1, "GROUP_MEMBER_ID": "1","GROUP_MEMBER_TYPE_ID":"4","GROUP_ID":"1", "TITLE": "CSR", "PHONE": "555-555-1212", "FNAME": "JOHN", "LNAME": "SMITH"}]
I have been trying to use angular.extend to no avail:
// local json objects to view result sets
var mLocalJson = {};
var mProdJson = {};
var mCombinedJson = {};
var teamApp = angular.module('teamApp', [])
teamApp.controller('mainController', function($scope, $http) {
$scope.documentsLocal = [];
$scope.documentsProd = [];
$scope.documentsCombined = [];
$scope.loadDataLocal = function () {
$http.post("php/getTeamsLocal.php")
.then(function(resultLocal) {
$scope.documentsLocal = resultLocal.data;
mLocalJson = resultLocal.data;
});
};
$scope.loadDataProd = function () {
$http.post("php/getTeamsProd.php")
.then(function(resultProd) {
$scope.documentsProd = resultProd.data;
mProdJson = resultProd.data;
});
};
$scope.loadDataCombined = function(){
mCombinedJson = angular.extend($scope.documentsCombined, $scope.documentsProd, $scope.documentsLocal);
};
});
I have tried a for loop. I have tried the following:
$scope.loadDataCombined = function(){
mCombinedJson = angular.extend($scope.documentsCombined, mProdJson, mLocalJson);
};
No matter what I have tried mCombinedJson is NULL

The API is not returning a JavaScript object. It is returning a JavaScript array with contents of one JavaScript object.
Use angular.extend to combine the objects inside the array.
var array1 = [{"ID": 1, "TITLE": "CSR", "PHONE": "555-555-1212", "FNAME": "JOHN", "LNAME": "SMITH"}];
var array2 = [{"ID": 1, "GROUP_MEMBER_ID": "1","GROUP_MEMBER_TYPE_ID":"4","GROUP_ID":"1"}];
var combinedArray = [angular.extend(array1[0],array2[0])];
console.log(combinedArray);
<script src="//unpkg.com/angular/angular.js"></script>

I used for loops to solve my issue:
$scope.loadDataProd = function () {
$http.post("php/getTeamsProd.php")
.then(function(resultProd) {
$scope.documentsProd = resultProd.data;
mProdJson = resultProd.data;
for (var i = 0; i < mLocalJson.length; i++) {
for (var j = 0; j < mProdJson.length; j++) {
if (mLocalJson[i].TEAM_ID == mProdJson[j].TEAMM_ID) {
mCombinedJson.push([{
"TEAM_GROUP_ID": $scope.documentsLocal[i].TEAM_GROUP_ID,
"TEAM_GROUP_MEMBER_ID": $scope.documentsLocal[i].TEAM_GROUP_MEMBER_ID,
"TEAM_GROUP_DESC": $scope.documentsLocal[i].TEAM_GROUP_DESC,
"TEAM_GROUP_MEMBER_TYPE_DESC": $scope.documentsLocal[i].TEAM_GROUP_MEMBER_TYPE_DESC,
"TEAM_ID": $scope.documentsProd[j].TEAMM_ID,
"TEAMM_DESC": $scope.documentsProd[j].TEAMM_DESC,
"TEAMM_EMAIL": $scope.documentsProd[j].TEAMM_EMAIL,
"TEAMM_EXTENSION": $scope.documentsProd[j].TEAMM_EXTENSION,
"TEAMM_EZLYNX_USERNAME": $scope.documentsProd[j].TEAMM_EZLYNX_USERNAME,
"TEAMM_FAX": $scope.documentsProd[j].TEAMM_FAX,
"TEAMM_NAME": $scope.documentsProd[j].TEAMM_NAME,
"TEAMM_PHONE": $scope.documentsProd[j].TEAMM_PHONE,
"TEAMM_QUEUE": $scope.documentsProd[j].TEAMM_QUEUE,
"TEAMM_QUEUE_GROUP": $scope.documentsProd[j].TEAMM_QUEUE_GROUP,
"TEAMM_QUEUE_KILLED": $scope.documentsProd[j].TEAMM_QUEUE_KILLED,
"TEAMM_QUEUE_SENT": $scope.documentsProd[j].TEAMM_QUEUE_SENT,
"TEAMM_TYPE": $scope.documentsProd[j].TEAMM_TYPE
}]);
}
}
}
});
};
$scope.loadDataCombined = function(){
setTimeout(function(){
for (var i = 0; i < mLocalJson.length; i++) {
for (var j = 0; j < mProdJson.length; j++) {
if (mLocalJson[i].TEAM_ID == mProdJson[j].TEAMM_ID) {
mCombinedJson.push([{
"TEAM_GROUP_ID": mLocalJson[i].TEAM_GROUP_ID, // 1 - 7
"TEAM_GROUP_MEMBER_ID": mLocalJson[i].TEAM_GROUP_MEMBER_ID,
"TEAM_GROUP_DESC": mLocalJson[i].TEAM_GROUP_DESC, // Cereal Killers, Guns n Closes, etc...
"TEAM_GROUP_MEMBER_TYPE_DESC": $scope.documentsLocal[i].TEAM_GROUP_MEMBER_TYPE_DESC, // Director, Manager, Assistant Manager, Producer
"TEAM_ID": mProdJson[j].TEAMM_ID,
"TEAMM_DESC": mProdJson[j].TEAMM_DESC,
"TEAMM_EMAIL": mProdJson[j].TEAMM_EMAIL,
"TEAMM_EXTENSION": mProdJson[j].TEAMM_EXTENSION,
"TEAMM_EZLYNX_USERNAME": mProdJson[j].TEAMM_EZLYNX_USERNAME,
"TEAMM_FAX": mProdJson[j].TEAMM_FAX,
"TEAMM_NAME": mProdJson[j].TEAMM_NAME,
"TEAMM_PHONE": mProdJson[j].TEAMM_PHONE,
"TEAMM_QUEUE": mProdJson[j].TEAMM_QUEUE,
"TEAMM_QUEUE_GROUP": mProdJson[j].TEAMM_QUEUE_GROUP,
"TEAMM_QUEUE_KILLED": mProdJson[j].TEAMM_QUEUE_KILLED,
"TEAMM_QUEUE_SENT": mProdJson[j].TEAMM_QUEUE_SENT,
"TEAMM_TYPE": mProdJson[j].TEAMM_TYPE
}]);
}
}
}
}, 300);
$scope.lDc();
};
$scope.lDc = function(){
$scope.documentsCombined = mCombinedJson;
};

Related

Angular nested loop promises

I'm trying to build a Cordova/angular app with a SQLite plugin to make it work offline but I'm having a lot of trouble with the promise and asynchronous of the query to the database this is my situation:
I have 5 table configured like this:
Table Pages with id, title, template_id and body
Table Menu with id and tag
Table PageMenus with id and page_id and menu_id to associate page and menu
Table MeniItems with id menu_id and body with the "actual" element in teach menu
Table template with id and tag to select the right view
for compatibility reason (I'm using the same code for the webapp and the mobile app and for the webapp I call my API while on mobile I download all the content on the device) I need to retrive the pages in this format:
{
"id": 1
"body": "Welcome to the homepage",
"title": "Homepage",
"template_tag": "tab",
"menus": [
{
"id": 3,
"tag": "home_menu",
"menu_items": [
{
"menu_id": 3,
"body": "Movie"
},
{
"menu_id": 3,
"body": "Restaurant"
},
{
"menu_id": 3,
"body": "Messages"
},
{
"menu_id": 3,
"body": "Systems"
}
]
},
{
"id": 62,
"tag": "user_menu",
"menu_items": [
{
"menu_id": 62,
"body": "About"
},
{
"menu_id": 62,
"body": "Updates"
},
{
"menu_id": 62,
"body": "Help"
},
{
"menu_id": 62,
"body": "Reset Password"
},
{
"menu_id": 62,
"body": "Report/ Feedback"
}
]
}
]
}
I'm already able to get the right format but my problem is that the controller tries to access the body of the menu before is resolved so I get error undefined this is the code I'm using in my factory at themoment:
return {
getHomePage: function() {
// other function
},
getPage: function(id) {
var results = $q.defer();
function request() {
var res = {};
var queryPage = "SELECT pages.id, pages.body, pages.title, templates.tag AS template_tag FROM pages JOIN templates ON pages.template_id = templates.id WHERE pages.id = ?";
$cordovaSQLite.execute(db, queryPage, [id]).then(function(page) {
res = page.rows.item(0);
res.menus = [];
var queryMenus = "SELECT menus.id, menus.tag FROM menus JOIN page_menus ON menus.id = page_menus.menu_id WHERE page_menus.page_id = ?";
$cordovaSQLite.execute(db, queryMenus, [res.id]).then(function(menus) {
for (var i = 0; i < menus.rows.length; i++) {
var menu = {
id: menus.rows.item(i).id,
tag: menus.rows.item(i).tag,
menu_items: []
};
var queryMenuItems = "SELECT * FROM menu_items JOIN menus ON menu_items.menu_id = menus.id where menus.id = ?"
$cordovaSQLite.execute(db, queryMenuItems, [menus.rows.item(i).id]).then(function(menu_items) {
for (var i = 0; i < menu_items.rows.length; i++) {
menu.menu_items.push(menu_items.rows.item(i));
}
});
res.menus.push(menu);
};
results.resolve(res);
});
});
};
request();
return results.promise;
},
getMedia: function(id) {
// other function
}
};
It's a good practice to chain promises the way:
getSomething: function(...) {
return requestReturningPromise1.then(function(resultOfPromise1) {
// Do something here (prepare next request,...)
return requestReturningPromise2;
}).then(function(resultOfPromise2) {
// Do something here (prepare next request,...)
return requestReturningPromise3;
}).then(function(resultOfPromise3) {
// Do something here (prepare next request,...)
return finalReturn;
});
}
Nesting is reduced, it's more readable and easy to debug.
So applying it to your code gives something like this:
getPage: function(id) {
var res = {};
var queryPage = "SELECT pages.id, pages.body, pages.title, templates.tag AS template_tag FROM pages JOIN templates ON pages.template_id = templates.id WHERE pages.id = ?";
return $cordovaSQLite.execute(db, queryPage, [id]).then(function(page) {
res = page.rows.item(0);
res.menus = [];
var queryMenus = "SELECT menus.id, menus.tag FROM menus JOIN page_menus ON menus.id = page_menus.menu_id WHERE page_menus.page_id = ?";
return $cordovaSQLite.execute(db, queryMenus, [res.id]);
}).then(function(menus) {
var menuPromises = [];
for (var i = 0; i < menus.rows.length; i++) {
var menu = {
id: menus.rows.item(i).id,
tag: menus.rows.item(i).tag,
menu_items: []
};
var queryMenuItems = "SELECT * FROM menu_items JOIN menus ON menu_items.menu_id = menus.id where menus.id = ?";
var menuPromise = $cordovaSQLite.execute(db, queryMenuItems, [menus.rows.item(i).id]).then(function(menu_items) {
for (var i = 0; i < menu_items.rows.length; i++) {
menu.menu_items.push(menu_items.rows.item(i));
}
return menu;
});
menuPromises.push(menuPromise);
}
return Promise.all(menuPromises);
}).then(function(menus) {
for (var i = 0; i < menus.length; i++) {
res.menus.push(menus[i]);
}
return res;
});
}
Note that in the code above, the service itself returns a promise so you have to consume it like this in your controller:
MyService.getPage(id).then(function(page) {
// here, bind the result page to your controller scope ...
});
This is what I end up doing (I post it even if I don't think will be really helpful for someone else because is heavily based on the structure of my DB):
var promisePage = $cordovaSQLite.execute(db, "SELECT p.*, t.tag AS template_tag FROM pages AS p JOIN templates AS t ON p.template_id = t.id WHERE p.id = ?", [id]);
var promiseMenus = $cordovaSQLite.execute(db, "SELECT m.* FROM menus AS m JOIN page_menus AS pm ON m.id = pm.menu_id WHERE pm.page_id = ?", [id]);
var promiseMenuItems = $cordovaSQLite.execute(db, "SELECT mi.* FROM menu_items AS mi JOIN menus AS m ON mi.menu_id = m.id JOIN page_menus AS pm ON pm.menu_id = m.id WHERE pm.page_id = ?", [id]);
return $q.all([promisePage, promiseMenus, promiseMenuItems]).then(function(data) {
var page = data[0].rows.item(0);
var menus = data[1];
var menuItems = data[2];
// here there is some boring code to construct the page
return page;
Simply instead of querying the db for menu and menu items after I got the page I query all three element in parallel and then do all the work in a $q.all.

creating a service which holds values to be updated later with separate controllers

I am trying to create a service which holds values that I want to be able to update from other controllers. It's a fake financial tracker which allows me to update the values in this service. I can't get it to work and I know I may be setting it up incorrectly. Can someone help me out with this?
My code:
(function () {
"use strict";
var Bkbank = angular.module('Bkbank' []);
Bkbank.controller('dashboardCtlr', function ($scope, dashboardSrvs) {
/*User Data*/
$scope.userName = dashboardSrvs.userName;
$scope.acctNum = dashboardSrvs.acctNum;
$scope.startDate = dashboardSrvs.startDate;
$scope.checkingsTotal = dashboardSrvs.checkingsTotal;
$scope.savingsTotal = dashboardSrvs.savingsTotal;
$scope.investTotal = dashboardSrvs.investTotal;
$scope.ouncesUpdate = dashboardSrvs.ouncesUpdate;
$scope.debtBalance = dashboardSrvs.debtBalance;
$scope.goldSpot = dashboardSrvs.goldSpot;
/*Section Titles*/
$scope.userTitle = dashboardSrvs.userTitle;
$scope.servicesTitle = dashboardSrvs.servicesTitle;
$scope.checkingsTitle = dashboardSrvs.checkingsTitle;
$scope.savingsTitle = dashboardSrvs.savingsTitle;
$scope.investTitle = dashboardSrvs.investTitle;
$scope.debtTitle = dashboardSrvs.debtTitle;
$scope.savingsUpdateTitle = dashboardSrvs.savingsUpdateTitle;
});
Bkbank.service('dashboardSrvs', function () {
/*User Data*/
this.userName = "Tim Willson";
this.acctNum = 554887;
this.startDate = "01/12/75";
this.checkingsTotal = "56458.00";
this.savingsTotal = "98187.00";
this.investTotal = "34143.00";
this.ouncesUpdate = "30";
this.debtBalance = "10000.00";
this.goldSpot = "1138.10";
/*Section Titles*/
this.userTitle = "User";
this.servicesTitle = "Financial Services";
this.checkingsTitle = "Checkings";
this.savingsTitle = "Savings";
this.investTitle = "Investments";
this.debtTitle = "debt";
this.savingsUpdateTitle = "Update Savings Account";
});
}());
I am not fully clear with the question you have asked but what I understood is you want to get/set attribute values into service so that updates available to all the consumer controller(s). In such scenario you can create service as e.g.
app.service('dashboardSrvs', function() {
var userName = "Tim Willson"; //Set some default Value
return {
get userName() {
return userName;
},
set userName(val) {
userName = val;
}
}
});
And inside the controller you can update the userName as -
testService.userName = 'Mike Tyson';
Angular merge to the rescue!
I advise you in advance to read this great article about Angular copy / extend / merge objects. Article link here
var demoApp = angular.module("demoApp", []);
demoApp.service("dashboardService", function () {
var configObj = {
"userData": {
"userName": "A",
"acctNum": "B",
"startDate": "C"
}
};
return configObj;
});
demoApp.controller("appController", function ($scope, dashboardService) {
// Override the new values of the service with a new object
var newConfigValues = {
"userData": {
"userName": "X",
"acctNum": "Z"
}
};
var newConfigObj = angular.merge({}, dashboardService, newConfigValues);
console.log(newConfigObj); // "userName": "X", "acctNum": "Z", "startDate": "C"
});
As you can see, you can override all or just some values. If you do the latter, the original values in your service will be kept.
JSFiddle here

how to read a json in angularjs, assign it to variable and work on the variable

main.js
var myFarm = $http.get('farmList.JSON').success(function(data) {
$scope.farms= data;
});
var myFarm = $scope.farms;
var updateFarms = function(){
for (i = 1; i <= myFarm.length; i++)
{
// code to update farms
var sFarm = myFarm[i - 1];
//loop thru myFarm and update it
$scope.farms = myFarm; //assign updated farms back to farms
}
}
farmList.json
[
{"farmName": "A", "type": "B"},
{"farmName": "C", "type": "D"}
]
I wanna be able to get the json into a variable so that I can keep a copy. if farms are updated, I should be able to go update myFarm to a new one. how do I get to work with variable in asynchronous func like http.get?
$http.get returns a promise. You must evaluate then() and take the result and assign to your scope variable.
http.get('farmList.JSON').then(function(data) {
$scope.farms = data;
});
Use $scope.farms for everything:
$scope.farms = [];
$http.get('farmList.JSON').success(function(data) {
$scope.farms= data;
});
var updateFarms = function() {
for (i = 1; i <= $scope.farms.length; i++)
{
// code to update farms
var sFarm = myFarm[i - 1];
//loop thru myFarm and update it
}
};

Firebase realtime data in not getting added properly in scope variable angularjs

This is firebase structure for categories2.
and this is for subcategories2.
To display data on screen I want $scope.Categories [] to be filled in this format.
[{
"id": "1",
"display_with": "7",
"image": "/images/salt_sugar.png",
"name": "Salt & Sugar",
"subcategories": [{
"scid": "1",
"scname": "Sugar Products"
},
{
"scid": "5",
"scname": "Tea"
}
]
},
.
.
.
.
]
Logic for filling $scope.Categories [].
$scope.Categories = [];
var categoriesRef = firebase.database().ref('categories2');
categoriesRef.on('value', function(snapshot) {
$scope.Categories = [];
var recvCategories = [];
recvCategories = snapshot.val();
for (var j=0; j<recvCategories.length; ++j){
var category = recvCategories[j];
//alert (category);
if (category != undefined){
var category_modified = {};
category_modified.id = category.id;
category_modified.display_with = category.display_with;
category_modified.name = category.name;
category_modified.image = category.image;
var subcategories = [];
for(var key in category.subcategories) {
var subcategoriesRef = firebase.database().ref('subcategories2/' + key);
subcategoriesRef.on('value', function(snapshot2) {
subcategories.push(snapshot2.val());
});
}
category_modified.subcategories = subcategories;
$scope.Categories.push(category_modified);
}
}
$scope.$apply();
});
As soon as data is available in want to display it on screen. so i am using $scope.$apply();
The problem is data is not displaying properly. but once i go to other controller and come back to same controller, everything displays as expected.
Why subcategories information is not adding up properly in $scope.Categories[]
I just modified your fiddle. just check the following link https://jsfiddle.net/py3ofkyc/8/
function myFunction() {
var subcategories = [];
var subcategoriesRef = firebase.database().ref('subcategories2');
subcategoriesRef.on('value', function(snapshot2) {
subcategories = snapshot2.val();
var Categories = [];
var categoriesRef = firebase.database().ref('categories2');
categoriesRef.on('value', function(snapshot) {
var Categories = [];
var recvCategories = [];
recvCategories = snapshot.val();
_(recvCategories).forEach(function(value) {
var category = value;
if (category != undefined){
var category_modified = {};
category_modified.id = category.id;
category_modified.display_with = category.display_with;
category_modified.name = category.name;
category_modified.image = category.image;
var _subcategories = [];
for(var key in category.subcategories) {
var data = _.filter(subcategories, { 'scid': key });
_subcategories.push(data[0]);
}
category_modified.subcategories = _subcategories;
Categories.push(category_modified);
}
});
console.log(Categories);
});
});
}`

How to merge REST call results in Angular app more efficiently

I have an Angular SPA running on a SharePoint 2013 page. In the code, I'm using $q to pull data from 10 different SharePoint lists using REST and then merging them into one JSON object for use in a grid. The code runs and outputs the intended merged data but it's leaky and crashes the browser after a while.
Here's the code in the service:
factory.getGridInfo = function() {
var deferred = $q.defer();
var list_1a = CRUDFactory.getListItems("ListA", "column1,column2,column3");
var list_1b = CRUDFactory.getListItems("ListB", "column1,column2,column3");
var list_2a = CRUDFactory.getListItems("ListC", "column4");
var list_2b = CRUDFactory.getListItems("ListD", "column4");
var list_3a = CRUDFactory.getListItems("ListE", "column5");
var list_3b = CRUDFactory.getListItems("ListF", "column5");
var list_4a = CRUDFactory.getListItems("ListG", "column6");
var list_4b = CRUDFactory.getListItems("ListH", "column6");
var list_5a = CRUDFactory.getListItems("ListI", "column7");
var list_5b = CRUDFactory.getListItems("ListJ", "column7");
$q.all([list_1a, list_1b, list_2a, list_2b, list_3a, list_3b, list_4a, list_4b, list_5a, list_5b])
.then(function(results){
var results_1a = results[0].data.d.results;
var results_1b = results[1].data.d.results;
var results_2a = results[2].data.d.results;
var results_2b = results[3].data.d.results;
var results_3a = results[4].data.d.results;
var results_3b = results[5].data.d.results;
var results_4a = results[6].data.d.results;
var results_4b = results[7].data.d.results;
var results_5a = results[8].data.d.results;
var results_5b = results[9].data.d.results;
var combined_1 = results_1a.concat(results_1b);
var combined_2 = results_2a.concat(results_2b);
var combined_3 = results_3a.concat(results_3b);
var combined_4 = results_4a.concat(results_4b);
var combined_5 = results_5a.concat(results_5b);
for(var i = 0; i < combined_1.length; i++){
var currObj = combined_1[i];
currObj["column4"] = combined_2[i].column4;
currObj["column5"] = combined_3[i].column5;
currObj["column6"] = combined_4[i].column6;
currObj["column7"] = combined_5[i].column7;
factory.newObjectArray[i] = currObj;
}
deferred.resolve(factory.newObjectArray);
},
function (error) {
deferred.reject(error);
});
return deferred.promise;
};
Here's the REST call in CRUDFactory:
factory.getListItems = function (listName, columns){
var webUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getByTitle('"+listName+"')/items?$select="+columns+"&$top=5000";
var options = {
headers: { "Accept": "application/json; odata=verbose" },
method: 'GET',
url: webUrl
};
return $http(options);
};
And then here's the controller bit:
$scope.refreshGridData = function(){
$scope.hideLoadingGif = false;
$scope.GridData = "";
GlobalFactory.getGridInfo()
.then(function(){
$scope.GridData = GlobalFactory.newObjectArray;
$scope.hideLoadingGif = true;
});
};
UPDATE 1: Per request, Here's the HTML (just a simple div that we're using angular-ui-grid on)
<div ui-grid="GridOptions" class="grid" ui-grid-selection ui-grid-exporter ui-grid-save-state></div>
This code starts by declaring some get calls and then uses $q.all to iterate over the calls and get the data. It then stores the results and merges them down to 5 total arrays. Then, because my list structure is proper and static, I'm able to iterate over one of the merged arrays and pull data from the other arrays into one master array that I'm assigning to factory.newObjectArray, which I'm declaring as a global in my service and using as my grid data source.
The code runs and doesn't kick any errors up but the issue is with (I believe) the "getGridInfo" function. If I don't comment out any of the REST calls, the browser uses 45 MB of data that doesn't get picked up by GC which is then compounded for each click until the session is ended or crashes. If I comment out all the calls but one, my page only uses 18.4 MB of memory, which is high but I can live with it.
So what's the deal? Do I need to destroy something somewhere? If so, what and how? Or does this relate back to the REST function I'm using?
UPDATE 2: The return result that the grid is using (the factory.newObjectArray) contains a total of 5,450 items and each item has about 80 properties after the merge. The code above is simplified and shows the pulling of a couple columns per list, but in actuality, I'm pulling 5-10 columns per list.
At the end of the day you are dealing with a lot of data, so memory problems are potentially always going to be an issue and you should probably consider whether you need to have all the data in memory.
The main goal you should probably be trying to achieve is limiting duplication of arrays, and trying to keep the memory footprint as low as possible, and freeing memory as fast as possible when you're done processing.
Please consider the following. You mention the actual number of columns being returned are more than your example so I have taken that into account.
factory.getGridInfo = function () {
var deferred = $q.defer(),
// list definitions
lists = [
{ name: 'ListA', columns: ['column1', 'column2', 'column3'] },
{ name: 'ListB', columns: ['column1', 'column2', 'column3'], combineWith: 'ListA' },
{ name: 'ListC', columns: ['column4'] },
{ name: 'ListD', columns: ['column4'], combineWith: 'ListC' },
{ name: 'ListE', columns: ['column5'] },
{ name: 'ListF', columns: ['column5'], combineWith: 'ListE' },
{ name: 'ListG', columns: ['column6'] },
{ name: 'ListH', columns: ['column6'], combineWith: 'ListG' },
{ name: 'ListI', columns: ['column7'] },
{ name: 'ListJ', columns: ['column7'], combineWith: 'ListI' },
],
// Combines two arrays without creating a new array, mindful of lenth limitations
combineArrays = function (a, b) {
var len = b.length;
for (var i = 0; i < len; i = i + 5000) {
a.unshift.apply(a, b.slice(i, i + 5000));
}
};
$q.all(lists.map(function (list) { return CRUDFactory.getListItems(list.name, list.columns.join()); }))
.then(function (results) {
var listResultMap = {}, var baseList = 'ListA';
// map our results to our list names
for(var i = 0; i < results.length; i++) {
listResultMap[lists[i].name] = results[i].data.d.results;
}
// loop around our lists
for(var i = 0; i < lists.length; i++) {
var listName = lists[i].name, combineWith = lists[i].combineWith;
if(combineWith) {
combineArrays(listResultMap[combineWith], listResultMap[listName]);
delete listResultMap[listName];
}
}
// build result
factory.newObjectArray = listResultMap[baseList].map(function(item) {
for(var i = 0; i < lists.length; i++) {
if(list.name !== baseList) {
for(var c = 0; c < lists[i].columns.length; c++) {
var columnName = lists[i].columns[c];
item[columnName] = listResultMap[list.name][columnName];
}
}
}
return item;
});
// clean up our remaining results
for (var i = 0; i < results.length; i++) {
delete results[i].data.d.results;
delete results[i];
}
deferred.resolve(factory.newObjectArray);
},
function (error) {
deferred.reject(error);
});
return deferred.promise;
};
I would suggest to add some sort of paging option... It's perhaps not a great idea to add all results to one big list.
Next i would suggest against ng-repeat or add a "track by" to the repeat function.
Check out: http://www.alexkras.com/11-tips-to-improve-angularjs-performance/
Fiddler your queries, the issue is probably rendering all the elements in the dom... Which could be kinda slow ( investigate)

Resources