4

I am storing records in an IndexedDB. I need to write a function to get records and return them to in JSON format to a data grid. The values are also in JSON.

This code doesn't really work because of the asynchronous nature of the IndexedDB calls.

How can I rework this to better use of maybe a promise to get the data?

function getRecords(skip, take) {
    var transaction = db.transaction("docs", "readonly");
    var objectStore = transaction.objectStore("docs");
    var result = "";
    var request = objectStore.openCursor(IDBKeyRange.bound(skip,skip+take))
        .onsuccess = function(evt) {  
            var cursor = evt.target.result;  
            if (cursor) {  
                result = JSON.stringify(cursor.value) + ',';
                cursor.continue();
            }
            return result.substr(0, result.length-1);
        };
}

Called like this:

var recordData = '[' + getRecords(1,10) + ']';

Adding full code

<html>
    <head>
        <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script type="text/javascript">
            var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
            var db;
            window.refreshing = false;
            var peopleData = [ 
                             {"FILENAME":"/NewDesigMemo1026732160521.pdf","DOC":"5/23/2016 | New Desig Memo","PRT_DT":"5/23/2016","EC":"","STATE":"","DES":"CC","PRG_CODE":"","DIST":"","CNAME":""},
                             {"FILENAME":"/NewDesigMemo1026732160521.pdf","DOC":"5/23/2016 | New Desig Memo","PRT_DT":"5/23/2016","EC":"","STATE":"","DES":"CSR","PRG_CODE":"","DIST":"","CNAME":""},
                             {"FILENAME":"/AttendanceOutOfStateMemo102673220160521.pdf","DOC":"5/23/2016 | Attendance Out of State Memo","PRT_DT":"5/23/2016","EC":"","STATE":"","DES":"CSR","PRG_CODE":"","DIST":"","CNAME":""},
                             {"FILENAME":"/Attend1026732160521.pdf","DOC":"5/23/2016 | Attendance","PRT_DT":"5/23/2016","EC":"","STATE":"","DES":"CM","PRG_CODE":"","DIST":"","CNAME":""},
                             {"FILENAME":"/NewMemo1026732160521.pdf","DOC":"5/23/2016 | New Desig Memo","PRT_DT":"5/23/2016","EC":"","STATE":"","DES":"CM","PRG_CODE":"","DIST":"","CNAME":""},
                            ];

            var peopleData2 = [ 
                              {"FILENAME":"/Attend102673220160312.pdf","PRT_DATE":"3/14/2016","EC":"","DOC":"3/14/2016 | CM Attendance","CRID":null,"PRG_CODE":"","STATE":"","DES":"","DATE_SENT":null,"PRG_DESC":null,"YEAR":null,"ISSUE":"","DIST":null,"CNAME":""},
                              {"FILENAME":"/RMagazine.aspx?I=r_spring_2016&P=1026732","PRT_DATE":"","EC":"","DOC":"R Magazine Spring 2016","CRID":null,"PRG_CODE":"","STATE":"","DES":"","DATE_SENT":null,"PRG_DESC":null,"YEAR":null,"ISSUE":"Spring 2016","DIST":null,"CNAME":""},
                              {"FILENAME":"/Packet+Notification+CSR+CC+20160309ALM.html","PRT_DATE":"3/9/2016","EC":"20160317LLM","DOC":"3/9/2016 | Packet Notification","CRID":null,"PRG_CODE":"","STATE":"","DES":"","DATE_SENT":null,"PRG_DESC":null,"YEAR":null,"ISSUE":"","DIST":null,"CNAME":"WTH"},
                              {"FILENAME":"Eval20160317LLM1026732.pdf","PRT_DATE":"","EC":"20160317LLM","DOC":"Evaluation_Packet","CRID":null,"PRG_CODE":"ALM","STATE":"LA","DES":"","DATE_SENT":null,"PRG_DESC":null,"YEAR":null,"ISSUE":"","DIST":null,"CNAME":"WTH"},
                              {"FILENAME":"Eval20160315LPR1026732.pdf","PRT_DATE":"","EC":"20160315LPR","DOC":"Evaluation_Packet","CRID":null,"PRG_CODE":"PR","STATE":"LA","DES":"","DATE_SENT":null,"PRG_DESC":null,"YEAR":null,"ISSUE":"","DIST":null,"CNAME":"IPR"}
                             ]
            function open() {
                var request = indexedDB.open("DocsDB");
                var upgraded = false;
                request.onupgradeneeded = function(evt) {
                    upgraded = true;
                    console.log("upgraded ok");
                    var dbnew = evt.target.result;

                    dbnew.onerror = function(event) {
                        console.log("IndexedDB error: " + evt.target.error.code);
                    };

                    var objectStore = dbnew.createObjectStore(
                             "docs", { keyPath: "id", autoIncrement: true });

                    objectStore.createIndex("docname", "DOC", { unique: false });
                    objectStore.createIndex("printdate", "PRT_DT", { unique: false });
                }
                request.onsuccess = function(evt) {
                    db = request.result;
                    if (!upgraded && !window.refreshing) {
                        throw "Not upgraded";
                    }
                    console.log("open ok");
                    request.result.onversionchange = function(e) {
                        if (e.newVersion === null) { // An attempt is made to delete the db
                            e.target.close(); // Manually close our connection to the db
                        }
                    };

                    if(typeof db != 'undefined' && !window.refreshing) {
                        var store = getObjectStore(db);                   
                        for (i in peopleData) {
                            store.add(peopleData[i]);
                            console.log("Added:"+peopleData[i]);
                        }
                    }
                }
                request.onerror = function() {
                    throw "Error in open";
                }
            }

             function getObjectStore(db, mode = 'readwrite') {
                 if(typeof db != 'undefined') {
                     var tx = db.transaction('docs', mode);
                     return tx.objectStore('docs');
                } else {
                    return null;
                }
             }

            function obliterate() {
                var request = indexedDB.deleteDatabase("DocsDB");
                request.onsuccess = function() {
                    console.log("delete ok");
                    open();
                }
                request.onerror = function(event) {
                    throw "Error in obliterate.";
                }
            }
            $(document).ready(function(){
                if(window.performance) { 
                    if(performance.navigation.type  == 0 ) {
                        // The db already exists so delete it and re-create it so we don't have stale records.
                        obliterate(); 
                    } else {
                        window.refreshing = true;
                        open();
                    }
                }

                $("#btnAdd").click(function () {
                    var transaction = db.transaction("docs", "readwrite");
                    var objectStore = transaction.objectStore("docs");
                    for (i in peopleData2) {
                        var request = objectStore.add(peopleData[i]);
                        request.onsuccess = function (evt) {
                            // do something after the add succeeded
                        };
                    }

                });

                $("#btnPrint").click(function () {                
                    window.finished = false;
                    var output = $("#printOutput");
                    getRecordsAsync( 1,10).then( data => {
                        output.html(data);
                    });
                });
            }); 

            function getRecordsAsync(skip, take) {
                return new Promise((resolve, reject) => {
                    var transaction = db.transaction("docs", "readonly");
                    var objectStore = transaction.objectStore("docs");
                    var result = "";
                    var request = objectStore.openCursor(IDBKeyRange.bound(skip,skip+take))
                        .onsuccess = function(evt) {  
                            var cursor = evt.target.result;  
                            if (cursor) {  
                                result = JSON.stringify(cursor.value) + ',';
                                cursor.continue();
                            }
                            resolve(result.substr(0, result.length-1));
                        }
                        .onerror = function(err) {
                          reject(err);
                        };
                });
            }


            function getRecords(output, skip, take, filter) {
                var transaction = db.transaction("docs", "readonly");
                var objectStore = transaction.objectStore("docs");
                var result = "";
                var range;
                if(filter != "" ) {
                    objectStore.index('docname');
                    range = IDBKeyRange.upperBound(filter);
                }
                range = IDBKeyRange.only(skip,skip+take)

                var request = objectStore.openCursor(range)
                    .onsuccess = function(evt) {  
                        var cursor = evt.target.result;  
                        if (cursor) {  
                            result = JSON.stringify(cursor.value) + ',';
                            cursor.continue();
                        }
                        window.finished = true;
                    };
            }

                    /*
                    var transaction = db.transaction("docs", "readonly");
                    var objectStore = transaction.objectStore("docs");
                    var result = "";
                    var range;
                    skip = 1;
                    take = 10;
                    range = IDBKeyRange.bound(skip,skip+take);
                    var request = objectStore.openCursor(range).onsuccess = function(evt) {  
                        var cursor = evt.target.result;  
                        if (cursor) {  
                            output.html( output.html()+"</br >id: " + cursor.key + " is: " + JSON.stringify(cursor.value)); // output.html(JSON.stringify(cursor.value));
                            cursor.continue();
                        }
                    };                      
                    */

        </script>
    </head>
    <body>
    <!-- http://localhost:8040/idb_test3.html -->
        <div id="container">
            <input type="button" id="btnAdd" value="Add Records" />
            <br />
            <br />
            <input type="button" id="btnPrint" value="Print objectStore" />
            <br />
            <br />
            <output id="printOutput">
            </output>
        </div>
    </body>
</html>
MB34
  • 4,210
  • 12
  • 59
  • 110
  • Possible duplicate of [How do I convert an existing callback API to promises?](http://stackoverflow.com/q/22519784/1048572). – Bergi Jun 02 '16 at 20:46

1 Answers1

3

To promisify this code would be something like:

EDIT: Fixed stupid syntax error

function getRecordsAsync(skip, take) {
    return new Promise((resolve, reject) => {
        var transaction = db.transaction("docs", "readonly");
        var objectStore = transaction.objectStore("docs");
        var result = "";
        var request = objectStore.openCursor(IDBKeyRange.bound(skip, skip + take))
            .onsuccess = function(evt) {
                var cursor = evt.target.result;
                if (cursor) {
                    result = JSON.stringify(cursor.value) + ',';
                    cursor.continue();
                }
                resolve(result.substr(0, result.length - 1));
            }
            .onerror = function(err) {
                reject(err);
            };
    });
}


getRecordsAsync(1, 10).then(data => {
console.log(data);

EDIT

OK, I tracked down the error you were getting -- it was an uncaught rejection in the promise. I should have seen that myself.

This code catches the error properly.

I've tried to track down what the error is, but I wasn't getting anything useful out of the system and I don't know indexeddb at all.

            $("#btnPrint").click(function () {                
                window.finished = false;
                var output = $("#printOutput");
                getRecordsAsync(1,10).then( data => {
                    output.html(data);
                }).catch(err => {
                  console.log("There was an error calling getRecordsAsync");
                  console.log(event);
                });
            });
Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74
  • Using Chrome, getting 'Undexpected token {' on this line `return new Promise(resolve, reject) {` – MB34 Jun 02 '16 at 20:37
  • @MB34 Fixed that, sorry. – Jeremy J Starcher Jun 02 '16 at 20:41
  • Now getting this: `Uncaught (in promise) Event {isTrusted: true, type: "success", target: IDBRequest, currentTarget: null, eventPhase: 0…}` – MB34 Jun 02 '16 at 21:25
  • I've taken you as car as I can since I didn't have a fully runable code example to begin with. – Jeremy J Starcher Jun 02 '16 at 21:26
  • Posting full code...Haven't yet hooked up a datagrid but you use the Print button to run the code I need the promise for. The IndexedDB is created when the page is loaded and adds 5 records from peopleData. The Add button adds 5 records from peopleData2. – MB34 Jun 02 '16 at 21:29
  • I will be adding code to asynchronously add records to the IndexedDB from a web service and need capability to get "pages" of data from the IndexedDB in my grid. BTW, the DB is deleted and recreated when the page is first loaded or reloaded, NOT refreshed. – MB34 Jun 02 '16 at 21:32
  • @MB34 I took it once step further -- but now my lack of knowledge on indexeddb stops me. – Jeremy J Starcher Jun 02 '16 at 21:57