在视图更改之前,Firebase 功能不会 运行

Firebase function not running until view change

我在 angular 控制器中有一个 Firebase 函数。有一个按钮,当单击它时,它会获取选定的选项和类型输入并将它们存储到用户的对象中,如下所示:

{
    selected-option : input-value
}

这非常有效,但只有在更改视图时才有效。在我的例子中,两家航空公司都已经有数据,所以这个函数显示一个 $ionicPopup。 视图更改一次后功能绝对完美。这显然是个问题,我认为这是 $apply 或 $digest 问题。

这是我的控制器代码(由 "ISSUE RIGHT HERE" 标记的 Supected 位置):

.controller('ProgramCtrl', ['$scope', '$state', '$firebaseArray', 'facebook', '$ionicPopup', '$ionicLoading',
function($scope, $state, $firebaseArray, facebook, $ionicPopup, $ionicLoading) {
$scope.goBack = function() {
    $state.go('app.home');
}

$scope.show = function() {
    $ionicLoading.show({
      template: 'Loading...'
    });
};
$scope.hide = function(){
    $ionicLoading.hide();
};

// Get who is logged in
$scope.user = facebook.get();

// Array of airlines
var airRef = ref.child("airlines");
$scope.airlines = $firebaseArray(airRef);
$scope.selectedAir = {};
$scope.miles = {};

$scope.revealInput = function(num) {
  // Jquery variables
  $milesPoints = $(".milesPoints");
  $saveTicket = $(".saveTicket");
  // Will fade in visibility depending on num passed into function
  switch(num) {
      case 1:
          $saveTicket.prop("disabled", false);
          $saveTicket.fadeTo(400, 1);
          break;
      default:
          break;
  }
}

// Add program to user
$scope.addProgram = function () {
  // Connect to Firebase
  Firebase.goOnline();
  // Check for facebook user
  if(jQuery.isEmptyObject($scope.user)) {
      // Get Firebase user
      var authData = ref.getAuth();
      var theUser = ref.child("users").child(authData.uid);
      var selected = {};
      // Access user miles data
      // $scope.show();
      // ISSUE RIGHT HERE    
     theUser.child("miles").child($scope.selectedAir.name.$id).once("value", function(snapshot) {
          // Update scopes
              var exist = snapshot.exists();
              // Check if object id exists, if so notify user
              if(!exist) {
                  // Save and update program to user object
                  selected[$scope.selectedAir.name.$id] = $scope.miles.num;
                  theUser.child("miles").update(selected);
                  //$scope.hide();
                  $state.go("app.saved");
              } else {
                  // Popup alert
                  var alertPopup = $ionicPopup.alert({
                    title: 'Oops!',
                    template: "You already created this airline! Go to the 'Add Ticket' page to add more points."
                  });
                  alertPopup.then(function(res) {
                    console.log("You already created this airline! Go to the 'Add Ticket' page to add more points.");
                  });
              }
      })

  } else {
      var theUser = ref.child("users").child($scope.user.id);
      var selected = {};
      $scope.show();
      theUser.child("miles").child($scope.selectedAir.name.$id).once("value", function(snapshot) {
          var exist = snapshot.exists();
          if(!exist) {
              selected[$scope.selectedAir.name.$id] = $scope.miles.num;
              theUser.child("miles").update(selected);
              $scope.hide();
              $state.go("app.saved");
          } else {
              var alertPopup = $ionicPopup.alert({
                title: 'Oops!',
                template: "You already created this airline! Go to the 'Add Ticket' page to add more points."
              });
              alertPopup.then(function(res) {
                console.log("You already created this airline! Go to the 'Add Ticket' page to add more points.");
              });
          }
      })

    }
  }
  }])

感谢您的帮助,如果需要,我可以提供更多代码或屏幕截图。

问题出在这段代码中:

theUser.child("miles").child($scope.selectedAir.name.$id).once("value", function(snapshot) {
    $timout(function() {
          var exist = snapshot.exists();
          // Check if object id exists, if so notify user
          if(!exist) {
              // Save and update program to user object
              selected[$scope.selectedAir.name.$id] = $scope.miles.num;
              theUser.child("miles").update(selected);
              //$scope.hide();
              $state.go("app.saved");
          } else {
              // Popup alert
              var alertPopup = $ionicPopup.alert({
                title: 'Oops!',
                template: "You already created this airline! Go to the 'Add Ticket' page to add more points."
              });
              alertPopup.then(function(res) {
                console.log("You already created this airline! Go to the 'Add Ticket' page to add more points.");
              });
          }
    });
})

当您调用 once() 时,它开始 从 Firebase 加载数据。由于这可能需要一些时间,因此您传入一个回调函数,该函数在数据可用时调用。但是在回调函数被调用时,AngularJS 不再期待 $scope 的更新。

解决方案是将代码包装到 $timeout() 中,以确保在 AngularJS 准备好再次处理范围更改时执行它:

 theUser.child("miles").child($scope.selectedAir.name.$id).once("value", function(snapshot) {
      // Update scopes
          var exist = snapshot.exists();
          // Check if object id exists, if so notify user
          if(!exist) {
              // Save and update program to user object
              selected[$scope.selectedAir.name.$id] = $scope.miles.num;
              theUser.child("miles").update(selected);
              //$scope.hide();
              $state.go("app.saved");
          } else {
              // Popup alert
              var alertPopup = $ionicPopup.alert({
                title: 'Oops!',
                template: "You already created this airline! Go to the 'Add Ticket' page to add more points."
              });
              alertPopup.then(function(res) {
                console.log("You already created this airline! Go to the 'Add Ticket' page to add more points.");
              });
          }
  })

请注意,如果您使用 AngularFire 的 $firebaseObject()$firebaseArray() 原语,则不会发生此问题,因为它们会自动通知 AngularJS 范围更改。

我们收到这个问题很多。这是最近的一个: