angular ionic fails to update for some variables

2019-08-12 03:41发布

问题:

In my Ionic / Angular framework I update 2 variables inside a service (an $http.get().then() block):

for( var di = day; di <= endOfMonthDate; di++) {
  var flavor = days[di - 1];
  daysLeftCalendar.push( flavor[1]);    // dates right away !
}

var todaysFlavorIndex = -1;
for (var i = 0; i < days.length; i++ ) {
  if ((days[i])[0] == day) {
    todaysFlavorIndex = (days[i])[1];     
    todaysFlavorName = flavors[todaysFlavorIndex];    // only updates if you change tabs
  }
}

Then I have these accessor methods in my service that get called by my controller:

   return {
     // both of these are hit after switching to one of the two tabs which both reference these functions
    remainingFlavorIndexes: function() {
      return daysLeftCalendar 
    },
    getTodaysFlavorName: function() {
      return todaysFlavorName
    }
  };

Then in my only controller I expose these variables like this:

  $scope.remainingFlavorIndexes = Calendar.remainingFlavorIndexes();    // this one copies over right away !!
  $scope.todaysFlavorName = Calendar.getTodaysFlavorName(); // this one doesn't

Then in my view:

<div>  <!-- this one shows up right away -->
      {{remainingFlavorIndexes}}
</div>
<div>   <!-- these two only show up after switching tabs and returning -->
 <img class="scaled-image" src="img/{{todaysFlavorName[2]}}">
</div>
<div style="text-align: center;">
  {{todaysFlavorName[1]}}
</div>

How is it that I'm handling these 2 variables exactly the same, but todaysFlavorName is empty (even after the .then call returns)?

And why is it that when I switch tabs and come back they are populated?

Edit:

What is supposed to go into remaining flavor indexes is something like this:

[21,20,13,0,27,12,9,18,1,3,30,29,25,7,6,4,9,18,21,13]

And it works every time.

What is supposed to go into todaysFlavorName is:

[21, "peanut butter", "peanut_butter.jpg", "some meaningless text here"]

And it works only after I switch tabs.

回答1:

There is a big difference between both. In the case of daysLeftCalendar:

  • the service has an array
  • the controller calls the service function that returns a reference to that array
  • the http callback function pushes elements to this array

So, the controller has a reference to the array that is in the service. Whenever the array is modified in the service, it's also modified in the controller, since the controller and the service both share a reference to the same array.

In the case of todaysFlavorName:

  • the service defines a variable todaysFlavorName referencing an array
  • the controller calls the service function that returns a reference to that array
  • the http callback function doesn't modify this array. It assigns a new array to the variable todaysFlavorName.

So, in the end, the controller has a reference to the original array, whereas the service has a reference to the new array. Which explains why nothing changes in the view: the controller still references the old array.

When you change tab, I assume the controller is reinstantiated, the service function is called again, and the controller gets back the new value from the service.

The fix is quite easy: always get the value to display from the service, instead of caching the value in the controller. Replace

$scope.todaysFlavorName = Calendar.getTodaysFlavorName();

by

$scope.todaysFlavorName = function() {
    return Calendar.getTodaysFlavorName();
};

and

{{todaysFlavorName[1]}}

by

{{todaysFlavorName()[1]}}