Awesome
localForage-observable
Adds observables to localForage, providing a way to get notified whenever:
- a method that affects the database is invoked
- the value associated with a specific key changes
Requirements
- localForage v1.4.0+
- zen-observable (used by default) or RxJS 5
Usage
Currently localForage Observables should only be created after localforage.ready()
, so that localForage completes the initialization of the requested (or best matching) driver. Moreover, Observables will stop working in case you change the driver in use, after their creation.
Observe for changes with newObservable()
Creates an observable and subscribes to DB changes.
With this method Subscribers get notified with a LocalForageObservableChange
object.
This method can be invoked with a LocalForageObservableOptions
object as optional argument.
Observe everything
var observable = localforage.newObservable();
var subscription = observable.subscribe({
next: function(args) {
console.log('I observe everything', args);
},
error: function(err) {
console.log('Found an error!', err);
},
complete: function() {
console.log('Observable destroyed!');
}
});
Observe a specific key
var observable = localforage.newObservable({
key: 'testKey'
});
var subscription = observable.subscribe({
next: function(args) {
console.log('testKey has changed to:', args.newValue);
}
});
Observe specific method calls
var observable = localforage.newObservable({
// setItem: false,
removeItem: true,
clear: true
});
var subscription = observable.subscribe({
next: function(args) {
console.log(args.methodName + ' was called!');
}
});
Get a "live" Observable of a DB Item Value with getItemObservable(key)
Creates an observable for a specific key that returns the current DB value and every new saved value.
With this method Subscribers receive the initial and ongoing DB values for a specific key as it changes.
This method can be invoked with a LocalForageObservableOptions
object as extra optional argument.
var useProfileObservable = localforage.getItemObservable('UserProfile');
useProfileSubscription = useProfileObservable.subscribe({
next: function(value) {
setCurrentUserNameToPage(value.username);
}
});
Cancel an Observable Subscription
subscription.unsubscribe();
Value change detection
Deep value change detection is enabled by default. This way our Observable Subscribers get notified only when the value of the associated key actually changes. Obviously, deep equality checking adds some extra overhead, so in case that all you need is to get notified on any attempt to change a value, you can easily disable value checking:
var observable = localforage.newObservable({
key: 'testKey',
changeDetection: false
});
Cross-Tab Observables #5
Cross-tab event emission, observation and value change detection are disabled by default.
In order to enable it, you have to:
- call the
configObservables()
method to start emmiting cross-tab events:
localforage.configObservables({
crossTabNotification: true
});
- create observables with cross-tab observation enabled:
var observable = localforage.newObservable({
crossTabNotification: true,
changeDetection: false
});
The arguments passed to cross-tab observable callbacks, will also have the crossTabNotification
property set.
Cross-tab change detection
Cross-tab observation with change detection is also supported, but with some limitations.
The arguments passed to the callback will have the valueChange
property set to true but:
- the
oldValue
will always benull
and - the
newValue
will hold the value retrieved from the local db at the time that the notification arrived. In that case you can use:
localforage.configObservables({
crossTabNotification: true,
crossTabChangeDetection: true
});
var observable = localforage.newObservable({
crossTabNotification: true
});
API
interface LocalForageObservableOptions {
key: string;
setItem: boolean;
removeItem: boolean;
clear: boolean;
changeDetection?: boolean; // default true
}
interface LocalForageObservableChange {
key: string;
methodName: string;
oldValue: any;
newValue: any;
valueChange?: boolean;
success?: boolean;
fail?: boolean;
error: any;
crossTabNotification?: string;
}
Using a different Observable library
You can actually use any library compatible with the ES Observable spec proposal. For example, in order to make localForage-observable use the Observables of the RxJS, all you have to do is change the provided Observable Factory method:
localforage.newObservable.factory = function (subscribeFn) {
return Rx.Observable.create(subscribeFn);
};
TypeScript
First of all, include localforage
with an import statement appropriate for your configuration and import localforage-observable
right after it.
Normally, localforage-observable
will extend the prototype of locaforage
to include newObservable()
etc, but unfortunately the typings can't be updated. As a result you should use the exported extendPrototype()
method, which returns the provided localforage instance but with inherited typings that also include the extra methods of localforage-observable
.
import localForage from "localforage";
// OR based on your configuration:
// import * as localForage from "localforage";
import { extendPrototype } from "localforage-observable";
var localforage = extendPrototype(localForage);
localforage.ready().then(() => {
// TypeScript will find `newObservable()` after the casting that `extendPrototype()` does
var observable = localforage.newObservable();
});