javascriptcordovalocalforagecordova-sqlite-storage

What is the correct way to use localForage with Cordova?


I am trying to use localForage with the localForage-cordovaSQLiteDriver to setup persistent storage in a cordova app. It's not working and I keep getting the following entries logged to the console:

new transaction is waiting for open operation

I'm not sure I understand the localforage lifecycle correctly. This is what I have:

// 1) setup cordova SQL lite driver
localforage.defineDriver(window.cordovaSQLiteDriver).then(function() {

    // 2) set preferred driver order
    return localforage.setDriver([
        window.cordovaSQLiteDriver._driver, // <-- prefer cordovaSQLiteDriver
        localforage.INDEXEDDB,
        localforage.WEBSQL,
        localforage.LOCALSTORAGE
    ]);
})
.then(function() {
    // 3) wait for localForage to be ready
    return localforage.ready();
})
.then(function() {

    // 4) create a globally scoped app database
    window.appStorage = localforage.createInstance({
        version: 1.0,
        size: 52428800, // 50mb
        name: 'my-app-name',
        storeName: 'setup'
    });

    // 5) check if we're using cordova sql lite
    if (localforage.driver() !== window.cordovaSQLiteDriver._driver) {
        console.warn('Not using cordovaSQLiteDriver.');
    }

    // 6) write something
    return appStorage.setItem('message', 'It worked!'); // <-- only it doesn't 
})
.then(function() {
    // 7) get the value back out of the database
    return appStorage.getItem('message');
})
.then(function(message){
    // 8) write the value to the console
    console.log(message);
});

In my mind it should be printing It worked! to the console.


Solution

  • So, first of all, createInstance() returns a totally new & unrelated instance of localforage and reinitializes from scratch. So the new instance will try to settle on which driver to use, using the default driver preference order (IndexedDB, WebSQL, LocalStorage). The only thing that all localforage instances share is the available/defined drivers. So you can do something like this:

    localforage.defineDriver(window.cordovaSQLiteDriver).then(function() {
        window.appStorage = localforage.createInstance({
            version: 1.0,
            size: 52428800, // 50mb
            name: 'my-app-name',
            storeName: 'setup',
            driver: [
                window.cordovaSQLiteDriver._driver, // <-- prefer cordovaSQLiteDriver
                localforage.INDEXEDDB,
                localforage.WEBSQL,
                localforage.LOCALSTORAGE
            ]
            // OR instead of passing the `driver` option,
            // you can call `window.appStorage.setDriver()`
            // right after `createInstance()`
        });
    
        if (window.appStorage.driver() !== window.cordovaSQLiteDriver._driver) {
            console.warn('Not using cordovaSQLiteDriver before setItem.');
        }
    
        return appStorage.setItem('message', 'It worked!');
    })
    .then(function() {
        return appStorage.getItem('message');
    })
    .then(function(message){
        console.log(message);
        if (window.appStorage.driver() !== window.cordovaSQLiteDriver._driver) {
            console.warn('Not using cordovaSQLiteDriver after setItem.');
        }
    });