I am pretty new to Angular and have problems with making a synchronous operation. I have resolved few issues which came my way with the angular controller, where I get the error 'Cannot call method then of undefined' thrown from the newController file.
angular.module('newApp.newController', ['angularSpinner', 'ui.bootstrap'])
.controller('newController', function($q, $scope, utilityFactory, $http) {
    utilityFactory.getData().then(function(data) {
        console.log("success");
        console.log(data);
    });
});
angular.module('newApp.utility', [])
    .factory('utilityFactory', function($q, $http) {
        var utils = {};
        //This is a cordova plugin
        var getLauncher = function() {
            return window.plugin.launcher;
        };
        var success = function(data) {
            console.log(device);
            return device;
        }
        var fail = function(error) {
            console.log("error", error);
        };
        utils.getData = function() {
            /* Get the store number details initially before initalizing the application */
            if (window.plugin) {
                var launcher = getLauncher();
                console.log("Fetching data from device");
                //Cordova js is returning this method
                return launcher.getDevice(success, fail);
            }
        };
        return utils;
    })
                With the understanding that :
Launcher.prototype.getDevice = function(successCallback, failureCallback) {
    exec(successCallback, failureCallback, KEY, 'getDevice', []);
}
, we know that window.plugin.launcher.getDevice() returns undefined, not a data object. Instead, it provides its response via its success/failure callbacks. 
Therefore, to work with promises, window.plugin.launcher.getDevice() needs to be "promisified", involving the explicit creation of a new Promise() and its resolution/rejection by .getDevice's callbacks. (Simply wrapping in $q(...) is not the same thing, and won't work).
angular.module('newApp.utility', []).factory('utilityFactory', function($q, $http) {
    return {
        getDevice: function() {
            return $q.defer(function(resolve, reject) {
                window.plugin.launcher.getDevice(resolve, reject); // If this line throws for whatever reason, it will be automatically caught internally by Promise, and `reject(error)` will be called. Therefore you needn't explicitly fork for cases where `window.plugin` or `window.plugin.launcher` doesn't exist.
            }).promise;
        }
    };
});
Calling from the controller should now work :
angular.module('newApp.newController', ['angularSpinner', 'ui.bootstrap']).controller('newController', function($q, $scope, utilityFactory, $http) {
    return utilityFactory.getDevice().then(function(data) {
        console.log(data);
    }).catch(function(error) {
        console.error(error);
    });
});
                            return launcher.getDevice(success, fail);
this line is the issue, I would just wrap it with a promise:
    return $q(launcher.getDevice.bind(launcher, success, fail));
Edit: also you need to take care of else condition, so code would be:
    utils.getData = function() {
        /* Get the store number details initially before initalizing the application */
        if (window.plugin) {
            var launcher = getLauncher();
            console.log("Fetching data from device");
            //Cordova js is returning this method
            return $q(launcher.getDevice.bind(launcher, success, fail));
        }
        return $q.resolve(); // or $q.reject(reason);
    };
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With