I am trying to add localForage support to the pure-form Web Component by creating a global instance of localForage:
// create a global appStorage object that mimics localStorage API (greater storage)
window.appStorage = localforage.createInstance({
driver: [
localforage.INDEXEDDB,
localforage.WEBSQL,
localforage.LOCALSTORAGE
],
name: 'product-name',
version: 1.0,
storeName: 'app'
});
And assigning it to an instance of pure-form via the storage
attribute:
<pure-form src="path-to-schema.json" storage="appStorage"></pure-form>
Internally, pure-form executes window[self.storage]
to get a handle to the storage object and uses .getItem
, .setItem
to set and retrieve values synchronously.
Trouble is localForage is asynchronous, meaning .getItem
, .setItem
expect to return values via a callback. Therefore my current logic won't work:
// get value from web storage
var storedContent = window[self.storage].getItem('item-key');
I realise I could wrap the call in a Promise, but as it stands pure-form does not require promises and I'd hate to add that dependency just for this.
What I would like to do is check if .getItem
or .setItem
require a callback, and if so, modify the code accordingly...
As @Dave-Newton pointed out in the comments:
there's no way to tell without looking at the source or docs. That said, almost any async call either takes a callback or uses promises.
Based on that, I created two functions that wrap calls to .getItem
and .setItem
and inspects their responses. If they return an instance of Promise, it resolves using .then
- otherwise executes the callback as normal:
/**
* Get a value from web storage regardless of whether it's sync or async
*/
function getStorageItem(storage, key, callback) {
if (typeof callback !== 'function') throw new Error('Invalid callback handler');
var result = storage.getItem(key);
if (result instanceof window.Promise) {
result.then(callback);
}
else {
callback(result);
}
}
/**
* Set a value in web storage regardless of whether it's sync or async
*/
function setStorageItem(storage, key, value, callback) {
var result = storage.setItem(key, value);
if (result instanceof window.Promise && callback) {
result.then(callback);
}
else if (callback) {
callback();
}
}
Which means I can now do:
// get value from web storage
getStorageItem(webStorage, key, function(value) {
if (value) {
// whatever I want with the value
}
});