Load data from storage before continue function


#1

Hello everyone,

I have a problem with storage. Inside of my home.ts file, in my constructor, i load my configprovider, like this:

  constructor(public configProvider:ConfigProvider, private navCtrl:NavController) {

      this.configProvider = configProvider;
      this.configProvider.startConfig();

      this.navCtrl = navCtrl;
      if (this.configProvider.current==null && this.configProvider.type==null){
          this.push.setRoot('WelcomePage');
      }
  }
  startConfig()
  {
      this.storage.ready().then(() => {
          this.storage.get('current').then((val) => {
              this.current = val;
          });
          this.storage.get('type').then((val) => {
              this.salaryType = val;
          });

      });
  }

While startconfig is loading, home.ts continues and because of that current and type are always null. When my app is pushed to welcomepage the values are loaded. So my temporarily solutions is to check the values there again and push back to home.ts again, but that is not an very good solution.

tl;dr
basicly I need to wait on the startconfig to finish, but I dont know if and how.
Can somebody help me?
Thanks in advance


#2

Hey @nathantaal Yes in fact I have written a solution to this problem - it is not exactly straightforward to solve! There are solutions to this of varying levels of complexity. I suspect most people do something similar to this:

this.storage.ready().then(() => {
         this.storage.get('somekey').then((someval) => {
             this.events.publish('somekey', someval);
         });
     });

And then you can subscribe to that same event and you know when the value is ready.

I have taken this one step further (ok well - several steps further) and I have built a decorator function that you simply attach to your class variables:

@IonicStorage() someVar: string;

The class comes with its own event service that you then subscribe to (there is a reason for this), and in that event you can do whatever you need to do. The decorator itself uses Storage underneath, and therefore uses whatever storage medium you have selected - it doesn’t care about that part. The design of the decorator is very heavily based on ngx-store if you want to look at it.

I am in the process of converting this into a proper package, which is sadly much much more work than my simple in-app code. I can either share what I have or I will see if I can get this published tomorrow, I’ve been wanting to do so for ages because I see this type of question here more or less weekly.


#3

Hi

I have some troubles understanding why you are doing an assign to this.configProvider and navCtr in the constructor, possibly overriding (or at least redoing) what the Direct Injection system is providing you in the constructor header definition (public configProvider:ConfigProvider, private navCtrl:NavController)

Secondly, I believe it is sound practice for your providers methods to always be returning a value. If it is a sync function, just the plain vanilla value. If it is async (like the startConfig()), a promise or an observable, which the caller handles.

That way, the navCtrl gets called with the appropriate value once the async is completed

Imho, you are trying to cover for async issues using sync patterns. Other people handle this through setTimeout, which again is a similar antipattern to solve async. But very creative.

The solution provided by @engineerapart may work, but in my view not necessarily the easiest way out. Nor making you aware how to deal with async.

So I would code a bit like below :

Regards

Tom


#4

The reason I made the decorator is because if you want to save more than 1 or 2 values in Storage, you have now polluted every single view - every single provider - with the boilerplate async code and after awhile it gets hard to read.

There’s no avoiding the fact that this process is asynchronous but there is a distinct reason that async/await were invented instead of saying “everyone should use Promises because you don’t want to cover up that it’s async!”

Sync patterns are much easier to reason about, and again, sure 1 or 2 times is fine but once you start doing this 6, 7, 15 times you will want the framework to help you manage it. Thus why I created the decorator. And it doesn’t at all avoid the fact that this is async - it simply allows your view to do 1 thing, and you listen for an event that tells you that the data you need is ready and do something useful with it.

Same code, but compartmentalized so that managing it is easier. In fact this pattern is by far the easiest way out - I no longer pay any attention to this issue in my apps.

In your example you have tightly bound: a) the source of the data, b) the fact that the data is stored async, and c) the navigation model of the view. If any ONE of those changes you now have to update that everywhere in your app. Instead, it is better to reason about the data itself, not how it is stored.


Working with async behaviour of new Ionic Storage
#5

Thx
Valuable insights!
Tom