0

i have seen many posts on this but for some reason I continue to run into a problem. I am returning multiple promises with $q.all. Each returned promise (from different vendors) is returning identically formatted arrays of objects. After everything is returned and everything is then processed into a single array of objects and then I need to sort the array of objects based on one of three SORT values : (vendor, price, price_estimate)

But when its returned to my controller nothing is sorted.

Sample Object: { "vendor" : "Aaa Company", "product" : "This prod", "description" : "this cool prod", "price" : 27.50, "price_estimate" : 23.25, "category" : "tool", ... } .factory('Products', function($http,$q,promise1,promise2,promise3,promise4,promise5) { var prods = [] ; function sortProds(key) { prods.sort(function(a,b) { if (key == "vendor") { return ((x<y) ? -1 : ((x > y) ? 1: 0)) ; } else { return parseFloat(a.key) - parseFloat(b.key) ; } }) ; } function getProds() { prods = [] ; $q.all([promise1(),promise2(),promise3(),promise4(),promise5()]).then(function(response){ var z=0 ; // process all results, ie: [0][{a:1,b:2,c:3},{a:4,b:5,c:6}], [1]:[{a:7,b:8,c:9} for (var y=0;y<response.length;y++) { // process individual result,ie: [{a:1,b:2,c:3},{a:4,b:5,c:6}] for (var x=0;x<response[y].length;x++) { response[y][x].prodID = z++ ; // reset prodID prods.push(response[y][x]) ; } } // sort option could be 'vendor','price','price_estimate' prodInfo.sortBy = getDB("prod_sortOption") ; sortProds(prodInfo.sortBy) ; }); } return { all: function() { return [prods,prodInfo.sortBy] ; } } }) 

Because I can't get the above to work, I then tried auto-sorting the returned results in the controller, but it too is not working. In my controller:

 $scope.doSort = function(key,prodList) { prodList.sort(function(a,b) { var x = a[key]; var y = b[key] ; if (key == "vendor") { return ((x<y) ? -1 : ((x > y) ? 1: 0)) ; } else { return parseFloat(a.key) - parseFloat(b.key) ; } }) ; return prodList ; } var returnedProds = Products.all() ; $scope.prods = $scope.doSort(prodInfo.sortBy,returnedProds[0]) ; // $scope.prods is what is used to in my template to populate the web view. 

HOWEVER, if the user in the webview does a manual sort on a button click that has ng-click="doSort('price',prods)" it works as intended...buts its the same doSort that isn't working on the auto-sorted returned results.

I hope all this makes sense. I can't figure out why its not sorting in the service...or again during the auto-sort upon returned results....but then does work when manually done. Ugh!

2
  • where is prodInfo defined in your factory?
    – floor
    CommentedJan 30, 2018 at 21:30
  • plunker or codepen link where you can reproduce the issue?CommentedJan 30, 2018 at 21:50

1 Answer 1

0

Unless I'm confused on your implementation, I recommend you don't have 2 functions that do the exact same thing. Use Products.sortProds() for both manual sorting and automatic sorting.

Here is my factory. I mocked the response array to return 1 product object from each promise. I overrided the getDB() call with a static string set to price. Also, I exposed every object and function in order to call getProds() from my component's $onInit, as I don't see your call to it. So the only difference is the synchronicity.

factory method

function ProductsFactory() { return { prods: [], prodInfo: {}, all: function() { return [this.prods,this.prodInfo.sortBy] ; }, sortProds: function(key) { this.prods.sort(function(a,b) { var x = a[key]; var y = b[key] ; if (key == "vendor") { return ((x<y) ? -1 : ((x > y) ? 1: 0)) ; } else { return parseFloat(a[key]) - parseFloat(b[key]) ; } }) ; }, getProds: function() { this.prods = [] ; var response = [ [{ "vendor": "Aaa Company", "product" : "This prod", "description" : "this cool prod", "price" : 27.50, "price_estimate" : 23.25, "category" : "tool", }], [{ "vendor": "Zaa Company", "product" : "This prod", "description" : "this cool prod", "price" : 22.90, "price_estimate" : 23.25, "category" : "tool", }], [{ "vendor": "Haa Company", "product" : "This prod", "description" : "this cool prod", "price" : 20.20, "price_estimate" : 23.25, "category" : "tool", }], [{ "vendor": "Gaa Company", "product" : "This prod", "description" : "this cool prod", "price" : 96.69, "price_estimate" : 23.25, "category" : "tool", }], [{ "vendor": "Waa Company", "product" : "This prod", "description" : "this cool prod", "price" : 69.69, "price_estimate" : 23.25, "category" : "tool", }], ]; var z=0 ; // process all results, ie: [0][{a:1,b:2,c:3},{a:4,b:5,c:6}], [1]:[{a:7,b:8,c:9} for (var y=0;y<response.length;y++) { // process individual result,ie: [{a:1,b:2,c:3},{a:4,b:5,c:6}] for (var x=0;x<Object.keys(response[y]).length;x++) { response[y][x].prodID = z++ ; // reset prodID this.prods.push(response[y][x]) ; } } // sort option could be 'vendor','price','price_estimate' //prodInfo.sortBy = getDB("prod_sortOption") ; this.prodInfo.sortBy = 'price'; this.sortProds(this.prodInfo.sortBy) ; }, } 

The price won't sort unless you do:

return parseFloat(a[key]) - parseFloat(b[key]) ; 

a.key => a[key]
b.key => b[key]

You also did not define the variables x and y in your sortProds() method

var x = a[key]; var y = b[key] ; 

implementation

this.$onInit = function() { Products.getProds(); Products.sortProds(Products.prodInfo.sortBy); $scope.prods = Products.all()[0]; $scope.Products = Products; // expose to vm scope console.log($scope.prods); // logs sorted array of product objects } 

I only had 30 minutes for this so I'm sorry if my answer is lacking. But for me, it works. If this doesn't work for you still, make sure your promises are returning the correct data in the correct format (2d array).

3
  • I tried pairing down my code to the basics so it wouldn't be a huge post, I guess I missed some of the critical things. and didn't edit it properly. Thanks for spending as much time as you did on it. Looking at your response now to analyze your solution to get it to work with my implementation.
    – rolinger
    CommentedJan 31, 2018 at 14:37
  • in the $onInit function, what is the $scope.Products = Products do? It looks like you are assigning the whole factory to $scope.Products yes? What does this accomplish?
    – rolinger
    CommentedFeb 1, 2018 at 4:51
  • @rolinger Sorry for a late response. Maybe you've figured it out by now. Basically, with $scope.Products = Products, you can simply do ng-click="Products.sortProds('price')" in your template. I realize now that you were just showing that your doSort method worked, but not your sortProds(). I convoluted my answer a little bit. The key flaw was that you were not defining x and y in your sortProds method, but you were in your doSort method. That's why sortProds() wasn't working iirc.CommentedFeb 3, 2018 at 18:44

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.