Promise in constructor


#1

Hello, I’m trying to make a settings service (sqlstorage) that gets loaded in app.ts and then injected to a bunch of pages without having to reload them.

The settings.ts service looks like:

import {Injectable} from '@angular/core';
import {Storage, SqlStorage} from 'ionic-angular';
@Injectable()
export class Settings {
    storage: Storage;
    dummy1: string='default';
    constructor(){
        this.storage = new Storage(SqlStorage, {name:'settings_data'});
        this.storage.get('settings_prop').then((settings) => {
            data = JSON.parse(settings);
            this.dummy1=data.dummy1
        }
    save(){
          let data = {
              dummy1: this.dummy1
          };        
        this.storage.set('settings_prop', JSON.stringify(data)).then(() => {
            window.location.reload();
        });

The app.ts looks like:

import {Settings} from './providers/settings/settings';       
 @App({
  templateUrl: 'build/app.html',
   providers: [Settings],
    config: {}
})
class MyApp {
    constructor(private app: IonicApp, private platform: Platform,
               public settings: Settings) {}

And a page.ts should look like:

import {Settings} from '../../providers/settings/settings';
@Page({
  templateUrl: 'build/pages/page1/page1.html',
})
export class Page1{
  constructor(public settings: SettingsService) {
    console.log(this.settings.dummy1)
  }

Initial setting for settings.dummy1 is ‘default’. If I change the value and do save in sqlstorage with something like ‘newvalue’, I would expect that exiting and loading again the app, my page Page1 would log ‘newvalue’ instead of ‘default’, as I expect the app constructor load the settings before entering in Page1

However, I’ve seen that this doesn’t always work. storage.get… then is a Promise, so I really don’t know when settings are really loaded once the object is created.

My newbie question is: What should be the correct way of doing this with ionic2? I don’t want to load settings from sqlstorage on each page but populate them from app.ts. Should I create an event to drive this? add a getSettings method and wait the promise to end to continue? how?

Thanks in advance for all this forum


#2

First, please if you’re going to put that many code, try to format correctly to be able to understand easier the code.

Now, there’s a lot of approaches you could take, the easiest one is using a method in service to return a promise that get the value from the database.

Another more advanced is using the Rxjs BehaviorSubject, by creating one of those and subscribing to it from page.ts you will get the last emitted value from it, in the service you just emit the value when getting the resolve from the database, that way you don’t need to call the database get each time since the BehaviorSubject stores the last value emitted.

I’m sure there are a whole lot of other creative implementations depending on your intended functionality.


#3

In addition to @luchillo17’s good advice, don’t reference the window object in a service. Services should not be interacting with the view layer.


#4

Yes, I fully agree with your advice. I was also not confortable on including that in service, but I’m a newbie in this and let that as future task.


#5

Code reformated. As I didn’t saw the code tag in the bar, i though that I cannot use it. thanks

BehaviorSubject seems to much complicated for me. I’ll try the Promise approach in the app.ts as I would like to avoid loading the database on each page.


#6

Code formatting uses the github markdown, format the code with 3 backticks and the ext of the language like ```js, this is how it would look:

import {Settings} from '../../providers/settings/settings';
@Page({
  templateUrl: 'build/pages/page1/page1.html',
})
export class Page1{
  constructor(public settings: SettingsService) {
    console.log(this.settings.dummy1)
  }
}

#7

Thanks a lot!!! post looks better now.
PD: I’ve noticed that ```ts also works, so used this one