【问题标题】:AngularJS sorting q.all array of objects from service is not workingAngularJS从服务中排序q.all对象数组不起作用
【发布时间】:2018-01-30 20:51:41
【问题描述】:

我看过很多关于此的帖子,但由于某种原因,我继续遇到问题。我用 $q.all 返回多个承诺。每个返回的承诺(来自不同的供应商)都返回格式相同的对象数组。返回所有内容后,然后将所有内容处理为单个对象数组,然后我需要根据三个 SORT 值之一对对象数组进行排序:(vendor, price, price_estimate)

但是当它返回到我的控制器时,什么都没有排序。

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] ;
    }
  }
})

因为我不能让上面的工作,然后我尝试在控制器中自动排序返回的结果,但它也不起作用。在我的控制器中:

  $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.

但是,如果 web 视图中的用户对具有 ng-click="doSort('price',prods)" 的按钮单击进行手动排序,它会按预期工作...但它与 doSort 相同,它无法处理自动排序的返回结果.

我希望这一切都有意义。我不知道为什么它不在服务中排序……或者在返回结果的自动排序期间再次排序……但是在手动完成时确实可以工作。啊!

【问题讨论】:

  • 你的工厂里prodInfo是在哪里定义的?
  • plunker 或 codepen 链接在哪里可以重现问题?

标签: javascript arrays angularjs sorting javascript-objects


【解决方案1】:

除非我对您的实现感到困惑,否则我建议您不要使用 2 个功能完全相同的功能。使用 Products.sortProds() 进行手动排序和自动排序。

这是我的工厂。我模拟了响应数组以从每个承诺中返回 1 个产品对象。我用设置为价格的静态字符串覆盖了 getDB() 调用。此外,我公开了每个对象和函数,以便从组件的 $onInit 调用 getProds(),因为我没有看到您对它的调用。所以唯一的区别是同步性。

工厂方法

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) ;
        },
    }

除非您这样做,否则价格不会排序:

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

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

您也没有在 sortProds() 方法中定义变量 xy

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

实施

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
  }

我只有 30 分钟的时间,所以如果我的答案不足,我很抱歉。但对我来说,它有效。如果这仍然对您不起作用,请确保您的承诺以正确的格式(二维数组)返回正确的数据。

【讨论】:

  • 我尝试将我的代码与基础知识配对,这样它就不会是一个巨大的帖子,我想我错过了一些关键的东西。并且没有正确编辑它。感谢您花费尽可能多的时间。现在查看您的回复以分析您的解决方案以使其与我的实现一起使用。
  • $onInit 函数中,$scope.Products = Products do 是什么?看起来您正在将整个工厂分配给 $scope.Products 是吗?这有什么作用?
  • @rolinger 抱歉回复晚了。也许你现在已经想通了。基本上,使用 $scope.Products = Products,您只需在模板中执行 ng-click="Products.sortProds('price')" 即可。我现在意识到您只是在证明您的 doSort 方法有效,而不是您的 sortProds()。我使我的答案有点复杂。关键缺陷是您没有在 sortProds 方法中定义 x 和 y,而是在 doSort 方法中。这就是为什么 sortProds() 不能在 iirc 工作。
猜你喜欢
  • 2018-09-18
  • 2020-12-19
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
  • 1970-01-01
  • 1970-01-01
  • 2011-10-12
  • 1970-01-01
相关资源
最近更新 更多