使用 $loaded 和 $firebaseObject 更新值 VS firebase SDK 更新。优点和缺点
Using $loaded with $firebaseObject to update value VS firebase SDK update. Pros and Cons
假设我有一个处理 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 完成后不会 return 承诺,我需要创造这个承诺,它有很多代码......
如果我使用 firebaseObject (angularFire 1.0),它将 运行 变成此处列出的问题:
根据@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() - 这是一个承诺,因此我的 firebase 服务中不需要 $q 服务。在我看来,它看起来更清晰了。两种方法都有效。
但是,根据文档:
"The $loaded() method should be used with care as it's only called once after initial load. Using it for anything but debugging is usually a poor practice."
我发现自己经常使用 $loaded!请建议解决此问题的最佳方法。
Firebase 有一个 JavaScript SDK,可将平台的功能暴露给 JavaScript 环境。 AngularFire 是该 SDK 之上的一个库,可以更轻松地将 Firebase 数据绑定到 AngularJS 网络界面。
你这里的例子是一个普通的数据操作。您没有将数据绑定到屏幕,因此您不需要 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
方法。但这不是必须的。
假设我有一个处理 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 完成后不会 return 承诺,我需要创造这个承诺,它有很多代码......
如果我使用 firebaseObject (angularFire 1.0),它将 运行 变成此处列出的问题:
根据@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() - 这是一个承诺,因此我的 firebase 服务中不需要 $q 服务。在我看来,它看起来更清晰了。两种方法都有效。
但是,根据文档:
"The $loaded() method should be used with care as it's only called once after initial load. Using it for anything but debugging is usually a poor practice."
我发现自己经常使用 $loaded!请建议解决此问题的最佳方法。
Firebase 有一个 JavaScript SDK,可将平台的功能暴露给 JavaScript 环境。 AngularFire 是该 SDK 之上的一个库,可以更轻松地将 Firebase 数据绑定到 AngularJS 网络界面。
你这里的例子是一个普通的数据操作。您没有将数据绑定到屏幕,因此您不需要 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
方法。但这不是必须的。