IonicStorage too slow


#1

I have this function in my provider which gives me settings for current user:

  initSettings() {
    this.storage.ready().then(() => {
      this.storage.get('userSettings').then((val) => {
        // console.log(`UserInfo ${val}`);
        if (val == null) {
          console.log('First Time storage setup started...');
          this.storage.set('userSettings', JSON.stringify(this.settings));
        }
        else {
          console.log(`Fetching settings from localStorage...`);
          this.settings = JSON.parse(val);
        }
      });
    });
  }

In app.component.ts,
I am initializing like this:

    setTimeout(() => {
      this.appTheme = this.User.getSettings().AppTheme;
      console.log(`App.component ${this.appTheme}`);
    }, 300);

It works fine on browser but doesn’t work on my android device, I even tried adding this thing in storage.ready() but still doesn’t work, any way I can handle the issue? :frowning:
Thanks and Regards.

EDIT 1:
Sorry I misclicked with incomplete quesiton.


#2

You will have to provide more information for us to be able to understand what you are doing:

In which provider does this live?[quote=“akshatbhargava123, post:1, topic:96472”]
if (val == null) {
console.log(‘First Time storage setup started…’);
this.storage.set(‘userSettings’, JSON.stringify(this.settings));
}
else {
console.log(Fetching settings from localStorage...);
this.settings = JSON.parse(val);
}
[/quote]

Can you explain the logic behind this in plain English please?[quote=“akshatbhargava123, post:1, topic:96472”]
setTimeout(() => {
this.appTheme = this.User.getSettings().AppTheme;
console.log(App.component ${this.appTheme});
}, 300);
[/quote]

Where exactly is this code?
What is this.User.getSettings()?

Also please post your ionic info output.


#3

Provider for getting user data from localStorage:

import { Platform } from "ionic-angular";

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

import { Storage } from '@ionic/storage';

@Injectable()
export class UserProvider {

  info: Info;
  settings: Settings;
  Defaults: {settings: Settings, info: Info};

  constructor(public platform: Platform, public http: Http, public storage: Storage) {

    console.log('UserProvider Initialisation Started...');
    this.storage.ready().then(() => {
      console.log(`Storage Driver: ${this.storage.driver}`)
    });

    this.Defaults = {
      settings: {
        Notifications: true,
        AppTheme: 'primary'
      },
      info: null
    };

    this.info = this.Defaults.info;
    this.settings = this.Defaults.settings;

    // ---------------------------------------------
    // Call Api for data and init into local storage
    // ---------------------------------------------

    this.initSettings();

  }

  initSettings() {
    this.storage.ready().then(() => {
      this.storage.get('userSettings').then((val) => {
        // console.log(`UserInfo ${val}`);
        if (val == null) {
          console.log('First Time storage setup started...');
          this.storage.set('userSettings', JSON.stringify(this.settings));
        }
        else {
          console.log(`Fetching settings from localStorage...`);
          this.settings = JSON.parse(val);
        }
      });
    });
  }

  getInfo(): Info {
    return this.info;
  }

  getSettings(): Settings {
    // console.log(`this.settings-> ${JSON.stringify(this.settings)}`);
    return this.settings;
  }

  update(info: Info, color?: string): void {
    
  }

  updateTheme(color: string): void {
    console.log(`Updating AppTheme to ${color}`);
    this.settings.AppTheme = color;

    this.storage.set('userSettings', JSON.stringify(this.settings));
  }

  SwitchNotifications() {
    console.log(`Switching notifications to ${this.settings.Notifications}`);
    this.settings.Notifications = !this.settings.Notifications;

    this.storage.set('userSettings', JSON.stringify(this.settings));
  }

}

export interface Info {
  Name: string;
  Sex: string;
  DOB: any;
  TOB: any;
  POB: string,
  Email: string;
  City: string;
}

export interface Settings {
  Notifications: boolean;
  AppTheme: string;
}

Why I thought of doing this in app.component.ts:

setTimeout(() => {
this.appTheme = this.User.getSettings().AppTheme;
console.log(App.component ${this.appTheme});
}, 300);

is because I wanted the plugin to give some time to initialize so I gave a hardcoded delay.

What I want to know?

An approach so that I can initialize localStorage or get data from it before my app code is being executed, in simple words before it jumps to next page from app.component.ts.

Ionic Info Output:

global packages:

@ionic/cli-utils : 1.4.0
Cordova CLI      : 7.0.1
Ionic CLI        : 3.4.0

local packages:

@ionic/app-scripts              : 1.3.7
@ionic/cli-plugin-cordova       : 1.4.0
@ionic/cli-plugin-ionic-angular : 1.3.1
Cordova Platforms               : android 6.2.3
Ionic Framework                 : ionic-angular 3.2.1

System:

Node       : v6.10.3
OS         : Windows 10
Xcode      : not installed
ios-deploy : not installed
ios-sim    : not installed
npm        : 3.10.10

Thanks and Regards.


#4

That provider has to return a promise that your normal code then can use - everything will always fail. Theoretically it could just return this.storage.get('userSettings'). Best get rid of this.settings in the provider as well, the storage is authority.

If you don’t want to “wait” for the storage every time, you have to implement your own promise that returns a local cache (what your this.settings tries to be right now) if it exists, otherwise waits for storage again and fills the cache before then resolving that promise with the value.


#5

I am not a pro so is there any tutorial out there on this topic of saving userData and retrieving it when app starts :frowning:
Please help, thank you very much.


#6

Well happy news I did using native Storage. I think native storage is even easy to use, are there any drawbacks of using it instead of ionic Storage?


#7

Don’t use setTimeout() here. Think in terms of contracts. The way you have written your provider, nobody outside it has any way of knowing when it is safe to call getSettings(). I would write it like this:

settings: Promise<Settings>;

constructor(private _storage: Storage) {
  this.settings = _storage.ready()
  .then(() => _storage.get('userSettings'));
}

updateTheme(color: string): Promise<void> {
  return this.settings.then((s) => {
    s.AppTheme = color;
    this.settings = Promise.resolve(s);
    return this._storage.set('userSettings', s);
  });
}

Any consumer can say:

settingsService.settings.then((settings) => { 
  // guaranteed reliable
});

#8

Thank you I got it, I will study promises again, I got kinda confused before.
Thank you very much.


#9

Another implementation strategy that is better when it’s important for listeners to be informed of changes to the settings is here.


#10

Ok though I feel this one easier :stuck_out_tongue:
Are there any drawbacks of native storage instead of ionic storage? I think it is easier to implement.
Thank you again.


#11

Yes. It won’t work in a browser environment, so developing using ionic serve will become impossible. Ionic-storage works seamlessly on both browser and device.