Firebase 3, AngularFire 2 in Ionic app data not up

2019-07-11 07:56发布

问题:

Firebase is known for its real-time data update, so this is a weird one for me.

I am using Firebase 3 (New firebase console app. Want to add authentication later) and AngularFire 2. I started the app using Ionic's tab template so the app.js' router config should be the same.

Click here to see a (90 second) video demo of the issue

I have my ionic app served to the browser using 'ionic serve --lab' so I can see iOS and Android view.

  • When I try to toggle data in one view (say iOS), the changes are instatly shown in firebase DB, but does now show immediately in the other view (Android) until I either toggle something, or change tabs in that view.

  • On the other hand, if I make a change in the firebase DB, then neither of the two views are updated until I either person an action or change tabs for each view.

Few other observations:

  • Sometimes on load, neither of the view has data loaded from firebase db until tabs are switched or 'Add Property' button is clicked for each view. (Least common)
  • Sometimes, one view has the data loaded, while the other does not until tabs are switched or 'Add Property' button is clicked for that view.
  • I uploaded the app to ionic.io to try it on my phone using ionic view, and I got same results where DB would update, but the views would not until a change was triggered.

HTML (containing toggles):

<ion-view view-title="Dashboard">
  <ion-content class="padding">
    <button class="button button-block button-positive" ng-click="addProperty()">Add Test Property</button>
    <div class="list" ng-repeat="(key, property) in properties">
      <ion-toggle class="item item-divider" ng-model="property.status" ng-true-value="'on'"
        ng-false-value="'off'" ng-change="togglePower(property, key)"> {{ property.name }}
      </ion-toggle>
    </div>
  </ion-content>
</ion-view>

Index.html

<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>

<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>

<!-- Firebase & AngularFire --> // I tried saving them and loading from locally
<script src="https://www.gstatic.com/firebasejs/3.2.0/firebase.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/2.0.1/angularfire.min.js"></script>

<script>
  // Initialize Firebase
  var config = {
    apiKey: "API_KEY",
    authDomain: "projectName.firebaseapp.com",
    databaseURL: "https://projectNamefirebaseio.com",
    storageBucket: "projectName.appspot.com"
  };
  firebase.initializeApp(config);
</script>

<!-- your app's js -->
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>

Controller.js

controller('DashCtrl', function ($scope) {
    var propertiesRef = firebase.database().ref('properties');

    propertiesRef.on('value', function (data) {
      $scope.properties = data.val();
    }, function (errorObject) {
      console.log("Error getting the properties: " + errorObject.code);
    });

    var id = 0;
    $scope.addProperty = function () {
      propertiesRef.push({
        name: "Test " + id++,
        status: "on"
      }).then(function () {
        console.log("Property Added!");
      });
    };

    $scope.togglePower = function (device, key) {
      propertiesRef.child(key).update({
        "status": device.status
      });
    };
};

Let me know if any additional is needed. I am not able to understand what seems to be the issue.

回答1:

As you can see, when you click the toggle in the android app all the toggles gets updated. This is because when you perform a click you trigger the digest cicle

You should call $scope.$apply() after updating your scope variable, or wrapping it in a timeout

controller('DashCtrl', function ($scope, $timeout) {
    var propertiesRef = firebase.database().ref('properties');

    propertiesRef.on('value', function (data) {
      $timeout(function() {
        $scope.properties = data.val();
      })
    }, function (errorObject) {
      console.log("Error getting the properties: " + errorObject.code);
    });
};