0

How to wait for a an AJAX response in IndexedDB to finish. I have the bellow code and if I run it async the second transaction links all responses to the last item from the first response. I'd liek to populate both stores of reports&receipts from the server on login so I can then work offline if needed. If I make it synchornous it works correctly but it is bad from user experience side as the app freezes a bit so I'd like to avoid that. Has anyone got a suggestion?

var DBRequest = window.indexedDB.open(IDBName, IDBVersion);
DBRequest.onerror = function(event) {
    console.log("error: ");
};

DBRequest.onsuccess = function(event) {
    var response = DBRequest.result;
    SExpenses.removeAll();
    var z=0;
    Ext.Ajax.request({
        url:App.url.expenses,
        method: 'GET',
        async:true,
        params: {
            user_guid: App.user.guid,
            limit: 25
        },
        success: function(res){
            var result = Ext.decode(res.responseText);
            var dataIDB = response.transaction(["ReportDataLocal"],'readwrite').objectStore("ReportDataLocal");
            dataIDB.clear();
            var receiptIDB = response.transaction(["ReceiptsLocal"],'readwrite').objectStore("ReceiptsLocal");
            receiptIDB.clear();

            var savedID, savedRecID;

            Ext.each(result.data, function(item){

                z++;
                SExpenses.insert(0,item);
                var newObject = response.transaction(["ReportDataLocal"], "readwrite")
                .objectStore("ReportDataLocal")
                .add({DESCRIPTION: item.DESCRIPTION, BILLING_QTY: item.BILLING_QTY,
                      TRAVEL_EXPENSES: item.TRAVEL_EXPENSES,REQUEST_TYPE_ID: item.REQUEST_TYPE_ID, 
                     SERVER_ID: item.SERVER_ID
                     });

                newObject.onsuccess = function(event){

                    savedID = event.target.result;
                    SExpenses.findRecord('SERVER_ID',item.SERVER_ID).set({ID:savedID});
                    Ext.Ajax.request({
                        url: App.url.receipts,
                        async: true,
                        method: 'GET',
                        params: {
                            Request_Log_RC: item.SERVER_ID
                        },
                        success: function(retrieve){

                            var result2 = Ext.decode(retrieve.responseText);

                            Ext.each(result2.data,function(item2){
                                SReceipt.add(item2);
                                var newReceiptIDB = response.transaction(["ReceiptsLocal"],'readwrite')
                                .objectStore("ReceiptsLocal");

                                newReceiptIDB.add({EXPENSE_AMOUNT: item2.EXPENSE_AMOUNT, EXPENSE_CURRENCY_ID:item2.EXPENSE_CURRENCY_ID,
                                                   EXPENSE_NAME: item2.EXPENSE_NAME, REPORT_ID: savedID, CURRENCY_ABB: item2.CURRENCY_ABB,
                                                   EXPENSE_IMAGE: null, SYNCED: true, DELETED: item2.DELETED,
                                                   SERVER_ID: item2.SERVER_ID, SERVER_REPORT_ID: item.SERVER_ID,
                                                   EXPENSE_EXCHANGE_RATE: null
                                                  });
                                newReceiptIDB.onsuccess = function(event){
                                    savedRecID = event.target.result;
                                    SReceipt.findRecord('SERVER_ID',item2.SERVER_ID).set({ID:savedRecID});

                                };   
                            });
                        }
                    });   
                };
            });   
        }
    });

};

1 Answer 1

1

So what you need to do is bind the item, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Basically if you ever do an async call looping over multiple items and you need the callback to keep the index of the original call you bind the index and pass it in.

var returnData = [];
var a = 10;
for(var i = 0; i < a.length; i++) {
    someAysncCall(function(data){
         returnData[i] = data;
    }).bind(null, i);
}

This will keep the i in the scope of the callback.

Looks like from your code you want item to stay in context so if you add bind to this

newObject.onsuccess = function(event){

                savedID = event.target.result;
                SExpenses.findRecord('SERVER_ID',item.SERVER_ID).set({ID:savedID});
                Ext.Ajax.request({
                    url: App.url.receipts,
                    async: true,
                    method: 'GET',
                    params: {
                        Request_Log_RC: item.SERVER_ID
                    },
                    success: function(retrieve){

                        var result2 = Ext.decode(retrieve.responseText);

                        Ext.each(result2.data,function(item2){
                            SReceipt.add(item2);
                            var newReceiptIDB = response.transaction(["ReceiptsLocal"],'readwrite')
                            .objectStore("ReceiptsLocal");

                            newReceiptIDB.add({EXPENSE_AMOUNT: item2.EXPENSE_AMOUNT, EXPENSE_CURRENCY_ID:item2.EXPENSE_CURRENCY_ID,
                                               EXPENSE_NAME: item2.EXPENSE_NAME, REPORT_ID: savedID, CURRENCY_ABB: item2.CURRENCY_ABB,
                                               EXPENSE_IMAGE: null, SYNCED: true, DELETED: item2.DELETED,
                                               SERVER_ID: item2.SERVER_ID, SERVER_REPORT_ID: item.SERVER_ID,
                                               EXPENSE_EXCHANGE_RATE: null
                                              });
                            newReceiptIDB.onsuccess = function(event){
                                savedRecID = event.target.result;
                                SReceipt.findRecord('SERVER_ID',item2.SERVER_ID).set({ID:savedRecID});

                            };   
                        });
                    }
                });   
            }.bind(null, item);

It should work

Sign up to request clarification or add additional context in comments.

1 Comment

Hello, If I do it like this i get an error "Uncaught TypeError: Cannot read property 'result' of undefined". If i bind both success calss one with .bind(item) and the other with .bind(item2) i don't get all under one report. But the receipts are still not in the right place. Some that should have them they don't and other have too much.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.