Ionic 2: Best practices for SqlStorage?

I have some questions about how to access storage/sqlstorage in ionic 2:

  1. How should I get a Storage instance in my app? Should I create a provider which provides one Storage instance for all app modules? Should each module just do “new Storage(SqlStorage)” to get an instance? What about concurrent transactions, is it possible with one of these ways?

  2. Setup and init DB:
    How shall I set up the needed DB structure on client when app starts? Where should I do this and how should I prevent the app from loading the UI until its initialized (structures and needed inserts done).

  3. Upgrade:
    In case I need to update DB with a new version, where should I do this? Probably same as #2.

Thanks in advance!

1 Like

That’s how I do it. I call it “Sink”.

I find the whole Storage API pretty much useless, and especially when it comes to transactions. Instead, I interact with the database handle directly, calling transaction and readTransaction on it. I typically have three core functions in Sink: query, exec and batch. They deal with the transactions, and all other functions can usually do what they need to by calling those three.

I do it inside a platform.ready() block kicked off in Sink’s constructor.

One way would be to expose an Observable from within Sink that fires a value when everything is initialized. Generally, I don’t find this useful, because usually UI components don’t care about the database structure being initialized; they care about when data has been fetched, which has its own schedule.

Same place the db is initialized. I keep a version table that stores the db version. If it doesn’t exist, the database must be built from scratch. If it does, but the version is old, that’s where the schema can be updated.

Thanks!

however, one thing is not clear:

One way would be to expose an Observable from within Sink that fires a
value when everything is initialized. Generally, I don’t find this
useful, because usually UI components don’t care about the database
structure being initialized; they care about when data has been fetched,
which has its own schedule.

Ok and how do you delay accessing DB until its initialized?
E.g.: My App shall have a login. So after start, i need to check if there is a logged in user, which is only possible when DB is initialized. Based on this I need to set login page or the main app page as root in app.ts. How would you do this?

I invert the control from the way you describe it, so there is never any “need to check if there is a logged-in user”. Instead, there is a separate authorization service (which may rely on Sink) which exposes an Observable<boolean> representing the authorization state. The application class may subscribe to this and swap its root page to the dashboard if it emits true or a login page if it emits false (for example). The authorization service, if it needs to rely on Sink, can ask Sink for a promise or observable of credentials, Sink will know how/when to wait for the data to be ready.

So, in general, I try to avoid designs where callers need values NOW and have to care when NOW is. Instead, providers provide things via futures (promises and observables) and consumers instead register subscription functions that say “here’s what I want to do with that data once it’s available”. This makes so many tricky sequencing bugs simply melt away.

Hm thanks a lot, i got the idea. Not sure how to implement it though, I’ll give it a try the next days, hopefully I get it work :wink:
However, i’m not yet sure how to handle “direct app entries” pointing to specific page, e.g. coming from another application/link/notification, with your approach, but maybe I can figure it out when I try to implement it.

Thanks!