Benjamin
Benjamin

Reputation: 31

Angularjs : mistake with $q

I have a button calling "getItems()" in my VisiteCtrl :

<button type="button" ng-click="getItems();">Populate</button>

Here is my VisiteCtrl :

function VisiteCtrl($scope, visiteService) {
  $scope.items = [];

  $scope.getItems = function() {
    var promise = visiteService.getItems();

    promise.then(function(items) {
      $scope.items = items;
    });
  };
}

And my 'visiteService' :

var module = angular.module('app', []);

module.service('visiteService', function($q) {
    this.getItems = function() {
        var deferred, result = [];
        deferred = $q.defer();
        var db = window.openDatabase('database', '1.0', 'database', 200000);

        db.transaction(function(tx) {
            tx.executeSql("CREATE TABLE IF NOT EXISTS todos(id integer primary key, item text, qty integer, type varchar(50))");
            /*tx.executeSql("DELETE FROM todos;");
            tx.executeSql("INSERT INTO todos(id, item, qty, type) VALUES (null, 'Oignon', 1, 'Course')");
            tx.executeSql("INSERT INTO todos(id, item, qty, type) VALUES (null, 'Viande', 2, 'Course')");
            tx.executeSql("INSERT INTO todos(id, item, qty, type) VALUES (null, 'Dormir', 1, 'Autre')");*/
            tx.executeSql("SELECT * FROM todos", [], function(tx, res) {

            for(var i = 0; i < res.rows.length; i++) {
                result.push({
                    id : res.rows.item(i).id, 
                    item : res.rows.item(i).item, 
                    qty : res.rows.item(i).qty, 
                    type : res.rows.item(i).type
                });
            }
            deferred.resolve(result);
        },
        function(tx, err) {
            console.log(err);
        });
    },
    function(err) {
        console.log(err);
    });

    return deferred.promise;
    }
});

On the first click on my button : - the service is called with no error - "deferred.resolve(result);" is called too - result containing data (console.log show me the contains). - ...but "promise.then(...)" never called.

After my second click, same things except that "promise.then(...)" is now called. And $scope.items contains my result (printed in my page).

I modified my Ctrl to test something :

function VisiteCtrl($scope, visiteService) {

  $scope.items = [];
  $scope.called = false;

  $scope.getItems = function() {
      if (!$scope.called) {
          $scope.called = true;
          alert("hip");

          var promise = visiteService.getItems();

          promise.then(function(items) {
            alert("hop");
            $scope.items = items;
          });
       }
  };
}

First click : I've got "Hip" Second click : I've got "Hop"

As if the second click resolve de $q.

I'm completely lost. Don't you have any idea ?

Thank you in advance for you answers.

Upvotes: 2

Views: 419

Answers (3)

Benjamin
Benjamin

Reputation: 31

Thank you all for your answers. Now it works !

Here is the VisiteService.js modified :

var module = angular.module('app', []);

module.service('visiteService', function($q, $rootScope) {

    this.getItems = function() {
        var deferred, result = [];
        deferred = $q.defer();
        var db = window.openDatabase('database', '1.0', 'database', 200000);

        db.transaction(function(tx)  {
            tx.executeSql("CREATE TABLE IF NOT EXISTS todos(id integer primary key, item text,     qty integer, type varchar(50))");
            /*tx.executeSql("DELETE FROM todos;");
            tx.executeSql("INSERT INTO todos(id, item, qty, type) VALUES (null, 'Oignon', 1,     'Course')");
            tx.executeSql("INSERT INTO todos(id, item, qty, type) VALUES (null, 'Viande', 2,     'Course')");
            tx.executeSql("INSERT INTO todos(id, item, qty, type) VALUES (null, 'Dormir', 1,     'Autre')");*/
            tx.executeSql("SELECT * FROM todos", [], function(tx, res) {
                for(var i = 0; i < res.rows.length; i++) {
                    result.push({
                        id : res.rows.item(i).id, 
                        item : res.rows.item(i).item, 
                        qty : res.rows.item(i).qty, 
                        type : res.rows.item(i).type
                    });
                }
                deferred.resolve(result);
                $rootScope.$apply()
            },
            function(tx, err) {
                console.log(err);
            });
        });
        return deferred.promise;
    }
});

Upvotes: 1

Eve-Amandine
Eve-Amandine

Reputation: 230

I'm not sure it can help you (it may be a mistake for a copy/paste) but you have one "error function" too many in your service:

The function this.getItems can't have a ", function(err) {}" after. I think it may create a problem with the returned promise. And, another thing, think to add a deferred.reject('theErrorYouWantToPass') in case there is an error.

this.getItems = function() {
    var deferred, result = [];
    deferred = $q.defer();
    var db = window.openDatabase('database', '1.0', 'database', 200000);

    db.transaction(function(tx) {
        tx.executeSql("CREATE TABLE IF NOT EXISTS todos(id integer primary key, item text, qty integer, type varchar(50))");
        /*tx.executeSql("DELETE FROM todos;");
        tx.executeSql("INSERT INTO todos(id, item, qty, type) VALUES (null, 'Oignon', 1, 'Course')");
        tx.executeSql("INSERT INTO todos(id, item, qty, type) VALUES (null, 'Viande', 2, 'Course')");
        tx.executeSql("INSERT INTO todos(id, item, qty, type) VALUES (null, 'Dormir', 1, 'Autre')");*/
        tx.executeSql("SELECT * FROM todos", [], function(tx, res) {

        for(var i = 0; i < res.rows.length; i++) {
            result.push({
                id : res.rows.item(i).id, 
                item : res.rows.item(i).item, 
                qty : res.rows.item(i).qty, 
                type : res.rows.item(i).type
            });
        }
        deferred.resolve(result);
    },
    function(tx, err) {
        console.log(err);
        deferred.reject(err);
    });

    return deferred.promise;
}

Upvotes: 1

karthik pamidimarri
karthik pamidimarri

Reputation: 305

 Calling $q.when takes a promise or any other type, if it is not a promise then it will
 wrap it in a   promise and call resolve. If you pass a value to it then it is never
 going to be rejected.
 [http://plnkr.co/edit/tX29CPDMhQnYchOVPdfZ?p=preview][1]
Here is my plunker link check it

Upvotes: 0

Related Questions