假设我有与Firebase操作的服务协议:
angular.module('myApp').factory('taskOfferService', ['FURL', '$firebaseArray', '$firebaseObject', '$q', 'taskService', taskOfferService]);
function taskOfferService(FURL, $firebaseArray, $firebaseObject, $q, taskService) {
var ref = new Firebase(FURL);
var Offer = {
acceptOffer: function(taskId, offerId, runnerId) {
var offerRef = ref.child('taskOffers').child(taskId).child(offerId);
var taskUpdate = $q.defer();
offerRef.update({accepted: true}, function(error) {
if (error) {
console.log('Update offer accepted value failed!');
} else {
var taskRef = ref.child('tasks').child(taskId);
taskRef.update({status: "assigned", runner: runnerId}, function(error) {
if (error) {
console.log('Update task status failed!');
taskUpdate.reject(false);
} else {
taskUpdate.resolve(true);
}
});
}
});
return taskUpdate.promise;
},
};
return Offer;
}
})();
我有一个控制器需要调用此服务,需要在更新成功时等待承诺 - 调用toaster.pop:
$scope.acceptOffer = function(offerId, runnerId) {
taskOfferService.acceptOffer($scope.selectedTask.$id, offerId, runnerId).then(function(){
toaster.pop('success', 'Offer is accepted.');
});
};
此代码有效,它遵循Firebase文档的建议。但正如您在我的服务中所看到的,为了获得承诺,我需要在更新回调中使用更新回调...我的观点是,Firebase SDK在完成后不会返回承诺,我需要创建此承诺这是很多代码...
如果我使用firebaseObject(angularFire 1.0),它将遇到此处列出的问题:saving new property overwrites firebase object
根据@sinan使用ANTIPATTERN,代码可以更清晰:
acceptOffer: function(taskId, offerId, runnerId) {
var o = $firebaseObject(ref.child('taskOffers').child(taskId).child(offerId));
o.$loaded().then(function(){
o.accepted = true;
o.$save().then(function(){
var oTask = $firebaseObject(ref.child('tasks').child(taskId));
oTask.$loaded().then(function(){
oTask.status = "assigned";
oTask.runner = runnerId;
oTask.$save();
});
})
},
关键是,使用“ANTIPATTERN”,我可以使用$ save() - 它返回一个promise,因此我的firebase服务中不需要$ q服务。在我看来,它看起来更加清晰。两种方法都有效。
但是,根据文件:
“$ loaded()方法应该小心使用,因为它只在初始加载后调用一次。除了调试之外用它做任何事情都是不好的做法。”
我发现自己使用$ loaded A LOT!请建议最好的方法来解决这个问题。
答案 0 :(得分:2)
Firebase有一个JavaScript SDK,可以将平台的功能公开给JavaScript环境。 AngularFire是该SDK之上的一个库,可以更轻松地将Firebase数据绑定到AngularJS Web界面。
这里的示例是一个简单的数据操作操作。您没有将数据绑定到屏幕上,因此您不需要AngularFire。我也认为没有必要使用承诺。
据我所知,这与你上一个脚本完全相同:
acceptOffer: function(taskId, offerId, runnerId) {
var offer = ref.child('taskOffers').child(taskId).child(offerId);
offer.update({ accepted: true }, function() {
var task = ref.child('tasks').child(taskId);
task.update({ status: "unassigned", runner: runnerId });
});
}
这不仅会缩短,还会阻止下载数据,然后再更新数据。
最好的部分?由于AngularFire是在常规Firebase JavaScript SDK之上构建的,因此它们可以完美地互操作。因此,如果在另一个地方您通过观察到$firebaseObject
的AngularJS视图实际显示任务或提供,它将立即显示更新的值。
如果您需要在保存acceptOffer
方法时执行某些操作,则可以传入回调:
acceptOffer: function(taskId, offerId, runnerId, callback) {
var offer = ref.child('taskOffers').child(taskId).child(offerId);
offer.update({ accepted: true }, function(error) {
if (!error) {
var task = ref.child('tasks').child(taskId);
task.update({ status: "unassigned", runner: runnerId }, callback);
}
else {
callback(error)
}
});
}
然后你调用它:
taskOfferService.acceptOffer($scope.selectedTask.$id, offerId, runnerId, function(error) {
if (!error) {
toaster.pop('success', 'Offer is accepted.');
}
else {
console.error('Something went wrong: '+error);
}
});
你绝对可以宣传acceptOffer
方法。但这不是必要的。