technogav / Grababite-1.3

version 1.3
0 stars 0 forks source link

Problem with non-persistant data #1

Open technogav opened 7 years ago

technogav commented 7 years ago

I have a problem when the page is refreshed my app loses all the data that it has initially pulled from the firebase database. When navigating through the app the correct data remains as expected however when I am making changes to the code and then refresh to reflect those changes all data disappears

Here is my Service initially pulling the data

.factory('RestaurantFactory', ['$firebaseArray', function($firebaseArray){

var rFactory = this;
var ref = firebase.database().ref('restaurants/');
var fbArray = $firebaseArray(ref);

var rests = [];
var loggedInRestaurant = [];
var deals = [];
var currentDeal = [];
var loggedInName = "Gavins Grub";

fbArray.$loaded().then(function(data) {
    angular.forEach(data, function(value) {
        rests.push(value); // Creates array with all restaurants

        if(value.name === loggedInName){
            loggedInRestaurant = value;
            deals = value.deals;        //copies all deals to variable          
        }

        angular.forEach(deals, function(value) {
            var x = new Date(value.startDate);
            var today = new Date();
            //if deal available set currentDeal
            if((today > x) && (value.uptake < value.numberAvailable)){      
                currentDeal = value;    //saves available deal to variable
            }
        }); 
    });     
});

I will just focus on one controller for simplicity and see how that controller calls the service

function ($scope, $stateParams, RestaurantFactory, $location) { "use strict"; $scope.deals =[]; $scope.loggedInRestaurant=[]; $scope.currentDeal = [];

$scope.deals = RestaurantFactory.getDeals();    

The initial page that loads in the app also calls this controller but does not use the $scope.deals variable. I wonder is the problem with the refresh that there is a delay in fetching the data? The next page uses the same controller so the data is ready waiting before the page gets rendered. If so how can I fix this without using a hacky timeOut function

dimkir commented 7 years ago

Well this behaviour of app "losing" data when you refresh app manually (or when it is refreshed automatically by ionic upon you saving changes to your source code) is intended. That's the way the app works.

Here's what happens:

When you load your app the first time, the browser first reads through all your javascript files. It reads through all of your source code - reads through all your services or controllers, and libraries but does NOT YET start executing them. (Yeah on the picture below it seems they're all loaded one by one. But that's only partial true - browser "gets to know them" one by one, but does not yet start executing them.

image


After all this is loaded, the browser finishes reading the rest of your index.html and builds up the DOM tree from your html.


Only now actual content of your app.js code starts executing (but there's not much in app.js except some basic configuration


Next your routes.js starts executing and at this point of time browser/angular learns about the fact that you have different routes and different screens.

The most important part in this route configuration is:

$urlRouterProvider.otherwise('/login');

which let's angular know which is the starting screen. And here intresting things start to happen.


From the above and below configuration

  .state('login', {
    url: '/login',
    templateUrl: 'templates/login.html',
    controller: 'dealsCtrl'
  })

angular now knows that it has to navigate to the "login" route (or state or page or screen - same thing), and it ONLY NOW STARTS MOVING IT'S ASS TO load fully and execute dealsCtrl. It may be worth noting that that in the very first step mentioned above, the browser(and angular) got to know such guy as dealsCtrl, but they didn't execute or loaded it fully.

Now as angular tries to load fully the dealsCtrl- it realizes in order for dealsCtrl to work properly, it needs few friends being ready for him first:

image

'$scope', '$stateParams', 'RestaurantFactory', '$location'

So angular goes and:

So after all of this has happened your deals(which you named login) page starts to show some real data and you are happy. Keep in mind that at this moment, this data (deal/restaurant data which you retrieved from the Firebase lives only in MEMORY of the browser confined to deals variable.

So what happened when you click to view different screen?


When you click on a link to go to different screen (keep in mind that now stopped using term "page". You have a "single page application - SPA" and this is why you do not navigate between pages (it's always same single page. More corretly said is that you navigate between screens even more correctly to say "you load different views into your screen". But why am I so **nal about terminology? Because when you stay on the same page and only load new views into your DOM, then it means that the memory of the browser is NOT reset. You simply load extra things to memory (like extra controllers and html-temlates), but everything you previously loaded (eg. app.js, libraries and more importantly RestaurantFactory and dealsCtrl still stay in memory and so stays RestaurantFactory.deals variable.

So now as you clicked on different link in the app - angular will intercept it and will check route configuration, previously loaded from routes.js.

Let's say you clicked on "analytics" link. To load "analytics" view, angular knows that it needs to fully load and execute analyticsCtrl. Here's how it happens:

 .controller('analyticsCtrl', ['$scope', '$stateParams', 'RestaurantFactory', '$location',
function ($scope, $stateParams, RestaurantFactory, $location) { /* ... */ }

From the lines above, angular learns that it needs a bunch of friends to make it work.


And now the answer - why does data not "persist" between page reloads? Well it is not supposed to. Whenever you reload page (or ionic reloads it for you during file saving), the whole process kicks in from the very beginning: browser starts clean and starts first by starting reading index.html and "getting to know" all your modules (in other words all your .js files) and so on.

How to solve this problem? Well as you have already imagined - the fact that all data disappears at every browser reload - is very annoying and developers have thought about this. This is why every modern browser comes with a small "built-in local database" into which you can store data you retrieved from firebase or user or any other external source. The methodology of accessing this database is called localStorage and you can find number of articles describing how to user localStorage with Ionic. Some links i found on google: https://www.thepolyglotdeveloper.com/2014/06/saving-data-with-ionicframework/ https://www.packtpub.com/books/content/persisting-data-local-storage-ionic

Should provide you a good start.

technogav commented 7 years ago

Ah ha, you have gone above and beyond answering this and have provided me with some good insight on how angular works under the hood. local storage is only ment to be used for development I guess. I will have a read of the links you provided and see if I can remedy the problem. It is quite annoying to restart the server every time :-)

dimkir commented 7 years ago

:)

Well localStorage is meant primarily for storing persistent data on the browser and also to make apps work when offline. Good usages of localStorage could be:

This may help as well: http://blog.ionic.io/building-an-ionic-app-with-offline-support-part-1/

Happy coding