heyred
heyred

Reputation: 2051

Handling asynchronous SQL call in AngularJS with $q

I have a Cordova cross platform app developed with AngularJS that implements a SQLite database. The idea is that users can sign in and their details will be stored in the SQLite database for access offline (e.g. Remember Me function).

On the login screen I run a query to check if there are values in the SQLite table as soon as the app is launched. Then depending on whether there are values in the table, I show the login confirmation screen OR ask users to enter their details.

The database is working as intended and I can save and read details to/from it. However, because the database handles calls asynchronously I have trouble displaying the correct UI to the user.

On my logins view I have a variable to hold a Boolean whether the SQLite table contains values. However, the variable is always empty/null because the asynchronous call responds after the variable is initialised.

I am trying to implement $q to initialise the variable once the asynchronous call is completed, but I am having trouble with the implementation.

My views controller looks as follows:

Controller

var login = angular.module("loginController", []);
login.controller("LoginController", function ($scope, $q, QueryRememberMe) {
    // Check if user logged in
    var logged = QueryRememberMe.query();
    logged.then(function (greeting) {
        alert("Success: " + greeting);
    }, function(reason) {
        alert("Failed: " + reason);
    });
    };
});

QueryRememberMe Service

var queryRememberMe = angular.module("queryRememberMe", []);
queryRememberMe.service("QueryRememberMe", function ($q, Database) {

    var db = Database.init();
    var tableName = "tb_UD_remember_me";
    var userLoggedIn = "";

    var myFunctions = {
        query: function () {
            return $q(function (resolve, reject) {
                var sql = 'SELECT * FROM ' + tableName;
                db.transaction(function (tx) { tx.executeSql(sql, [], myFunctions.success, myFunctions.error); });

                if (myFunctions.success) {
                    resolve('Hello, success!');
                }
                else {
                    reject('Greeting ERROR - is not allowed.');
                }
            });   
        },

        // Query success callback
        success: function (tx, results, tableName) {
            // There are no values in the table
            if (results.rows.length == 0) {
                userLoggedIn = false;
            }
            else {
                userLoggedIn = true;
            }
            return userLoggedIn;
        },

        // Query Error Callback
        error: function (tx, err) {
            alert("An error has occured - Unable to query SQL Table " + tableName);
        },
    }
    return myFunctions;
});

Upvotes: 0

Views: 351

Answers (1)

Paulson Peter
Paulson Peter

Reputation: 574

Try update like below (It is no tested).

In your service

var myFunctions = { 
    query: function () { 
        var deferred = $q.defer();
        var sql = 'SELECT * FROM ' + tableName;
        var success = function(tx, results, tableName) {
            if (results.rows.length == 0) {
                deferred.resolve({userLoggedIn: false});
            }
            else {
                deferred.resolve({userLoggedIn: true, message: 'Hello, success!'});
            }
        }
        var error = function(tx, err) {
            deferred.reject({userLoggedIn: false, message: 'An error has occured - Unable to query SQL Table'});
        }

        db.transaction(function (tx) {
            tx.executeSql(sql, [], success, error); 
        });
        return deferred.promise;
    }
};

In your controller

var logged = QueryRememberMe.query();
logged.then(
    function (greeting) {
        alert("Success: " + greeting.message);
    }, 
    function(reason) {
        alert(reason.message);
    }
);

Upvotes: 1

Related Questions