If you are using a .then
method it is most likely that the object that precedes it is a thenable (or an object that has a then method ). Usually those who implement this type of method are Promises . Looking at your code more closely we have
datosGrupos: function() {
var getGrupos, infoGrupos;
getGrupos = localStorage.getItem('GruposProf');
infoGrupos = JSON.parse(getGrupos);
return infoGrupos;
}
which you then call
obtenerGruposProf.datosGrupos().then(//....
The error occurs because the datosGrupos
function does not return a promise and therefore there is no .then
method. What returns that function as such is the data you have in the localStorage, a common and ordinary object.
To get a promise back you must do something like
angular.module('gruposProfesor', ['ionic', 'ngCordova'])
.factory('obtenerGruposProf', obtenerGruposProf);
obtenerGruposProf.$inject = ['$q'];
function obtenerGruposProf($q) {
return {
datosGrupos: function() {
var defer = $q.defer();
// creas un objeto Deferred que tiene un método resolve y reject
var getGrupos, infoGrupos;
getGrupos = localStorage.getItem('GruposProf');
infoGrupos = JSON.parse(getGrupos);
// resuelves la promesa con el valor obtenido
defer.resolve(infoGrupos) ;
// devuelves el .promise que es el que tiene el método then
return defer.promise;
}
};
}
You would basically be returning a promise with the future result already resolved. This is an error for two reasons
You are creating asynchrony in an operation that is inevitably synchronous.
Operations in localStorage are synchronous. The method getItem immediately returns a string, that is, the result of the operation, not a future result.
It's much simpler to write
var data = obtenerGruposProf.datosGrupos();
console.log(data);
what to write
obtenerGruposProf.datosGrupos().then(function(data) {
console.log(data);
});
since you are creating unnecessary nesting. This puts you one step closer to the callback-hell which is one of the reasons why promises exist.
Usually writing promises in that way is considered a antipatron since
Promises serve to make the asynchronous code retain most of the lost properties of the synchronous code such as flat indentation and a single channel for errors.
As you saw previously, you do not need to create indentation and in case of error you can use a simple try ... catch
In the Deferred antipattern, "deferred" objects are created for no reason, complicating the code.
There is a case in which yes you should write the code in this way and that is when, for example, you have to make an ajax call or return a stored result already. Basically you have two options, one is synchronous and the other asynchronous. In this case you can do this.
angular.module('gruposProfesor', ['ionic', 'ngCordova'])
.factory('obtenerGruposProf', obtenerGruposProf);
obtenerGruposProf.$inject = ['$q', '$http'];
function obtenerGruposProf($q, $http) {
return {
datosGrupos: function() {
var getGrupos, infoGrupos;
getGrupos = localStorage.getItem('GruposProf');
if (getGrupos) {
infoGrupos = JSON.parse(getGrupos);
var defer = $q.defer();
defer.resolve(infoGrupos);
return defer.promise;
} else {
return $http.get('/miapi/gruposprof');
}
}
};
}
Then you manipulate your data using
obtenerGruposProf.datosGrupos().then(function(data) {
localStorage.setItem('GruposProf', JSON.stringify(data));
console.log(data);
});
In this case the deferred if necessary since you can not know for sure if the call will be asynchronous or not and the use of .then
is fully justified.
Finally, keep in mind that if you want to cache the result of your ajax calls in the localStorage, there is already a service to do that.
Check out link .