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