更改服务器数据时,$ loaded无法正常工作

时间:2016-09-22 14:32:40

标签: angularjs join firebase firebase-realtime-database angularfire

我是firebase和angularjs的新手。对于我的销售应用程序,我想同时使用它们。所以,在我的应用程序中,我使用 AngularJS v1.5.8 + Firebase v3.3.0 + AngularFire 2.0.2 。我在firebase数据库中有销售和用户对象,并且有一个业务逻辑,一个用户可以销售多个产品,但一个产品只能有一个所有者(用户)。

以下是数据库中的用户销售对象:

{
  "sales" : {
    "-KQlb5N6A9rclc5qcWGD" : {
      "price" : 8,
      "quantity" : {
        "count" : 12,
        "type" : "porsiyon"
      },
      "status" : "sale",
      "title" : "Patlicanli Borek",
      "user" : "-KQ52OJd-lwoDIWzfYFT"
    },
    "-KQlcScsq8cidk7Drs04" : {
      "price" : 12,
      "quantity" : {
        "count" : 10,
        "type" : "porsiyon"
      },
      "status" : "sale",
      "title" : "Deneme",
      "user" : "-KQ5-mZBt6MhYy401gGM"
    },
    "-KQzXHwOv2rC73scjV46" : {
      "price" : 12,
      "quantity" : {
        "count" : 11,
        "type" : "porsiyon"
      },
      "status" : "sale",
      "title" : "Pacanga",
      "user" : "-KQ5-mZBt6MhYy401gGM"
    },
    "-KSCBgpArtnKunUuEuVr" : {
      "price" : 15,
      "quantity" : {
        "count" : 15,
        "type" : "porsiyon"
      },
      "status" : "sale",
      "title" : "Iskembe",
      "user" : "-KQ52OJd-lwoDIWzfYFT"
    }
  },
  "users" : {
    "-KQ5-mZBt6MhYy401gGM" : {
      "address" : "Halkali kucukcekmece",
      "email" : "burak.kahraman@gmail.com",
      "name" : "Burak Hero",
      "nick" : "Burak'in Mutfagi"
    },
    "-KQ52OJd-lwoDIWzfYFT" : {
      "address" : "Izmir kaynaklar",
      "email" : "ayse@gmail.com",
      "name" : "Ayse Kahraman",
      "nick" : "Ayse'nin Mutfagi"
    }
  }
}

我想要做的是,当我的应用程序打开时,它会显示所有销售以及相应的用户详细信息。 (就像letgo应用程序的主页一样)这意味着我应该在销售和用户对象之间实现简单的连接。据我在互联网和api文档中搜索,没有办法在一次调用firebase时实现这种连接。 (如果我错了,请纠正我)所以我使用下面的方法在 SalesService 中使用 $ loaded 函数来实现连接。

angular.
  module('core.sales')
  .service('SalesService', function ($firebaseArray, $firebaseObject, UsersService) {
this.getAllSalesJoin = function () {
      var sales;
      var refSales = firebase.database().ref('sales');
      sales = $firebaseObject(refSales);
      sales.$loaded()
        .then(function () {
          angular.forEach(sales, function (sale) {
            var saleUser = UsersService.getUserDetail(sale.user);
            saleUser.$loaded()
              .then(function () {
                sale.user = saleUser;
              });
          });
        });
      return sales;
    };
 });

如您所见,我正在获取所有销售,在完成后,循环每次销售以通过调用下面显示的另一个 UsersService 获取并设置相关的用户详细信息

angular.
  module('core.users')
  .service('UsersService', function ($firebaseArray,$firebaseObject) {
this.getUserDetail = function (userId) {
      var user;
      var refUser = firebase.database().ref('users/'+userId);
      user = $firebaseObject(refUser);
      return user;
    };
  });

到目前为止一切顺利,当我在我的Controller中调用 SalesService.getAllSalesJoin 函数并使用<pre>{{$ctrl.allSales | json}}</pre>打印JSON对象时,一切都按照我的意愿工作,下面是Controller代码并打印模板中的JSON对象。

angular.
  module('saleList').
  component('saleList', {
    templateUrl: 'MCTs/sale-list/sale-list-template.html',
    controller: ['SalesService','UsersService', function SaleListController(SalesService,UsersService,$scope) {

          this.allSales = SalesService.getAllSalesJoin();  
 }]
  });

模板显示合并的对象

{
  "$id": "sales",
  "$priority": null,
  "-KQlb5N6A9rclc5qcWGD": {
    "price": 8,
    "quantity": {
      "count": 12,
      "type": "porsiyon"
    },
    "status": "sale",
    "title": "Patlicanli Borek",
    "user": {
      "$id": "-KQ52OJd-lwoDIWzfYFT",
      "$priority": null,
      "address": "Izmir kaynaklar",
      "email": "ayse@gmail.com",
      "name": "Ayse Kahraman",
      "nick": "Ayse'nin Mutfagi"
    }
  },
  "-KQlcScsq8cidk7Drs04": {
    "price": 12,
    "quantity": {
      "count": 10,
      "type": "porsiyon"
    },
    "status": "sale",
    "title": "Deneme",
    "user": {
      "$id": "-KQ5-mZBt6MhYy401gGM",
      "$priority": null,
      "address": "Halkali kucukcekmece",
      "email": "burak.kahraman@gmail.com",
      "name": "Burak Hero",
      "nick": "Burak'in Mutfagi"
    }
  },
.....

但是问题是,当更改服务器数据(输入新销售或删除旧销售)时,angular会自动理解更改,但会将更改应用于视图而不实现或调用我的加入函数,它只打印仅销售对象而不是与用户合并的销售对象。下面是服务器数据更改后的显示对象。

{
  "$id": "sales",
  "$priority": null,
  "-KQlb5N6A9rclc5qcWGD": {
    "price": 8,
    "quantity": {
      "count": 12,
      "type": "porsiyon"
    },
    "status": "sale",
    "title": "Patlicanli Borek",
    "user": "-KQ52OJd-lwoDIWzfYFT"
  },
  "-KQlcScsq8cidk7Drs04": {
    "price": 12,
    "quantity": {
      "count": 10,
      "type": "porsiyon"
    },
    "status": "sale",
    "title": "Deneme",
    "user": "-KQ5-mZBt6MhYy401gGM"
  },
....

我很困惑,为什么它表现得那样?我的方法是使用 $ loaded 错误实现连接吗?或者我应该使用另一种方法来实现这种连接?我期待着看到你无价的建议和想法。

2 个答案:

答案 0 :(得分:0)

$loaded()仅在加载初始数据时触发。来自reference documentation(强调我的):

  

返回从数据库下载初始对象数据后解析的承诺

这是我经常说的主要原因:&#34;如果你正在使用$loaded(),那么你做错了&#34;。

您需要通过多次通话加入数据。在AngularFire中,您可以extend $firebaseArray执行此类操作。有关如何执行此操作的一个很好的示例,请参阅加藤的这个答案:Joining data between paths based on id using AngularFire

答案 1 :(得分:0)

感谢指南@Frank。我阅读了你的所有建议并找到了解决方案。为了提供stackoverflow知识并在这里帮助其他人是问题的完整解决方案。

我首先创建了一个新工厂,扩展$ firebaseArray并覆盖$$ added和$$更新方法,以便在每次更新或添加数据时对Users对象执行 join

angular.
  module('core.sales').factory("SalesFactory", function ($firebaseArray, Sales) {
    return $firebaseArray.$extend({
      $$added: function (snap) {
        return new Sales(snap);
      },

      $$updated: function (snap) {
        return this.$getRecord(snap.key).update(snap);
      }

    });
  });

angular.
  module('core.sales').factory("Sales", function ($firebaseArray, $firebaseObject) {
    var refUsers = firebase.database().ref('users');

    function Sales(snapshot) {
      this.$id = snapshot.key;

      this.update(snapshot);
    }

    Sales.prototype = {
      update: function (snapshot) {
        var oldTitle = angular.extend({}, this.title);
        var oldPrice = angular.extend({}, this.price);
        var oldQuantity = angular.extend({}, this.quantity);

        this.userId = snapshot.val().user;
        this.title = snapshot.val().title;
        this.status = snapshot.val().status;
        this.price = snapshot.val().price;
        this.quantity = snapshot.val().quantity;
        this.userObj = $firebaseObject(refUsers.child(this.userId));

        if (oldTitle == this.title && oldPrice == this.price && 
        oldQuantity.count == this.quantity.count && oldQuantity.type == this.quantity.type)
          return false;
        return true;

      },

    };

    return Sales;
  });

如您所见, SalesFactory 使用另一个名为销售的工厂。在该特定工厂中,我检索Sales对象的所有属性,并将它们分配给相应的属性。这就是我通过创建新属性来连接到Users对象的情况: this.userObj 缺少一件事就是调用新的Factory而不是$ firebaseArray

this.getAllSalesArray = function () {
      var sales;
      var refSales = firebase.database().ref('sales');
      sales = SalesFactory(refSales);
      return sales;
    };

总而言之,与相关用户一起加入的所有Sales对象都打印到视图中,

[
  {
    "$id": "-KQlb5N6A9rclc5qcWGD",
    "userId": "-KQ52OJd-lwoDIWzfYFT",
    "title": "Patlicanli Borek",
    "status": "sale",
    "price": 12,
    "quantity": {
      "count": 11,
      "type": "tabak"
    },
    "userObj": {
      "$id": "-KQ52OJd-lwoDIWzfYFT",
      "$priority": null,
      "address": "İzmir kaynaklar",
      "email": "ayse@gmail.com",
      "name": "Ayşe Kahraman",
      "nick": "Ayşe'nin Mutfağı"
    }
  },
  {
    "$id": "-KQlcScsq8cidk7Drs04",
    "userId": "-KQ5-mZBt6MhYy401gGM",
    "title": "Deneme",
    "status": "sale",
    "price": 12,
    "quantity": {
      "count": 10,
      "type": "porsiyon"
    },
    "userObj": {
      "$id": "-KQ5-mZBt6MhYy401gGM",
      "$priority": null,
      "address": "Halkalı küçükçekmece",
      "email": "burak.kahraman@gmail.com",
      "name": "Burak Hero",
      "nick": "Burak'ın Mutfağı"
    }
  },
...
]