2

I have factory that's using indexedDB and method getRecipe that needs this indexed db to receive data.

Problem is that indexedDB returns it's instance in asynchronous call and getRecipe is another method that returns it's value in asynchronous call.

I try to solve it via promises, but I failed.

app.factory('RecipesStorage', ['$q', function($q) { 
var getDb = function () {
   var deferred = $q.defer();

   var db;
   var request = indexedDB.open('recipes', 1);

   request.onupgradeneeded = function (e) {
       console.log('Upgrading indexedDb');
       var thisDb = e.target.result;

       if (!thisDb.objectStoreNames.contains('recipe')) {
           thisDb.createObjectStore('recipe');
       }
   }

   request.onsuccess = function (e) {
       db = e.target.result;
       window.db = db;
       deferred.resolve(db);
   }

   request.onerror = function (e) {
       console.error('Error when opening indexedDB');
   }

   return deferred.promise;
};

var getRecipe = function (recipeId, callback) {
        getDb().then(function(db) {
            var transaction = db.transaction(['recipe'], 'readonly');
            var objectStore = transaction.objectStore('recipe');

            var data = objectStore.get(recipeId);

            data.onsuccess = function (e) {
                var result = e.target.result;
                console.log('GetRecipe:', result);
                callback(result);
            }

            data.onerror = function (e) {
                console.error('Error retrieving data from indexedDB', e);
            }
        });
};

return {getRecipe:getRecipe};
}]);

But this doesent work. In getRecipe the function in then isn't invoked. I don't know where is problem.

5
  • Well is request.onsuccess ever called? Commented Nov 10, 2013 at 14:36
  • yes it is. But then nothing happens. Commented Nov 10, 2013 at 14:49
  • Just to make sure, try to add a then callback just before calling resolve. It works right? If it does have a look at what's returned by getDb(). Commented Nov 10, 2013 at 14:55
  • It's called before resolve. getDB returns object with then function, so I think this part is ok. Commented Nov 10, 2013 at 14:59
  • Do you know request.onsuccess is actually being called? Your then success function won't execute unless deferred.resolve is actually called. See Maxim Shoustin's answer for more details. Commented Nov 10, 2013 at 17:48

3 Answers 3

3

We can use promise chain to make it work.

(I don't have database so i simulated async response and wrapped data with $q)

Demo Fiddle

fessmodule.controller('fessCntrl', function ($scope, RecipesStorage) {

    $scope.alertSwap = function () {
       RecipesStorage.getDb()
                        .then(function (result) {
                           $scope.data = result;                           
                        }, function (result) {
                            alert("Error: No data returned");
                        });
    }

});

fessmodule.$inject = ['$scope', 'RecipesStorage'];

fessmodule.factory('RecipesStorage', ['$q', function ($q) {

    var getDb = function () {        
        var data = [{
            "PreAlertInventory": "5.000000",
            "SharesInInventory": "3.000000"
        } ];   
        var deferred = $q.defer();
        deferred.resolve(data);
        return getRecipe(data);        
    };

    var getRecipe = function(db){    
        var data = [{        
            "TotalSharesBought": "0.000000",
            "TotalShareCost": "0.000000",
            "EstimatedLosses": "0.000000"
        }]; 
        db.push(data[0]);
        var deferred = $q.defer();
        deferred.resolve(db);
        return deferred.promise;
    }

    var factory = {
        getDb: getDb
    };

    return factory;
}]);

Reference

enter image description here

  • You can chain promises to create code flows
  • Error propagates, so you can catch it on the end of the chain

enter image description here

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

Comments

0

I can't see a problem in your code. Maybe this plunker helps you to figure out where the problem is. I created it based on your code and it apparently works.

1 Comment

you're right. Somehow It starts working. Now the problem is somewhere with scope. It doesen't show in view until I write something into inputs. Then it refresh all values properly.
0

The real problem was that in my version I've used angular in version 1.0.8, but when I switched it to version 1.2.0 it starts working as expected. Thanks :)

Comments

Your Answer

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