使用 $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 方法。但这不是必须的。