我是firebase和angularjs的新手。对于我的销售申请,我想两者都用。所以,在我的应用程序中,我使用AngularJS v1.5.8 + Firebase v3.3.0 + AngularFire 2.0.2。我在firebase db中有sales和users对象,并且有一个业务逻辑,即一个用户可以销售多个产品,但一个产品只能有一个所有者(user)。
下面是数据库中的users和sales对象:{
"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的单个调用中实现这种连接。(请纠正我,如果我错了)所以我使用下面的方法使用$loaded函数在我的SalesService实现连接。
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;
};
});
到目前为止一切顺利,当我调用SalesService时。getAllSalesJoin函数并使用<pre>{{$ctrl.allSales | json}}</pre>
打印JSON对象,一切都如我所愿,下面是模板中的控制器代码和打印的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会自动理解这个变化,但它在没有实现或调用我的join函数的情况下将更改应用到视图中,它只是打印销售对象而不是与用户合并的对象。以下是服务器数据更改后的显示对象:
{
"$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连接错误吗?或者我应该使用另一种方法来实现这种连接?我期待着看到你无价的建议和想法。
$loaded()
仅在加载初始数据时触发。参考文档(重点是我的):
返回一个promise,当从数据库下载初始对象数据时被解析。
这就是我经常说:"如果你用的是$loaded()
,那你做错了"的主要原因。
你是对的,需要与多个调用连接数据。在AngularFire中,您可以扩展$firebaseArray
来执行这样的操作。有关如何做到这一点的一个很好的例子,请参阅Kato的回答:使用AngularFire
感谢frank的指导。我读了你所有的建议,找到了解决办法。对于贡献stackoverflow知识和帮助他人,这里是问题的完整解决方案。
我首先创建了一个新的工厂,扩展$firebaseArray并覆盖$$added和$$updated方法,以便在每次更新或添加数据时执行join to Users对象。
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的工厂。在这个特定的工厂中,我检索Sales对象的所有属性,并将它们分配给相应的属性。在这种情况下,我通过创建新属性this。userobj 来执行连接到Users对象有一件事是缺少的,只是调用新的工厂,而不是$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ğı"
}
},
...
]