Reputation: 1518
I'm a little bit confused how should I handle the promises in my situation.
This is my factory:
return {
getCategory: function(categoryId) {
var ref = firebase.database().ref().child('categories').child(categoryId);
var category = $firebaseObject(ref);
return category.$loaded().then(function() {
return category;
});
},
getEntry: function(categoryId, entryId) {
var ref = firebase.database().ref().child('entries').child(categoryId).child(entryId);
var entry = $firebaseObject(ref);
return entry.$loaded().then(function() {
return entry;
});
}
}
In my factory I try to avoid doing like this:
var d = $q.defer();
if() {
d.resolve();
}
return d.promise;
Because the $loaded() returns a promise itself.
And this is my controller:
var categoryId = 'abc';
var entryId = 'def';
// so here i'm getting the category
MyFactory.getCategory(categoryId)
.then(function(category) {
if(category.$value === null)
{
$scope.error = 'The category does not exist';
}
else if(new Date() > new Date(category.expireDate))
{
$scope.error = 'The category has expired';
}
else {
$scope.category = category;
// if no errors
return MyFactory.getEntry(category.$id, entryId);
}
})
.then(function(entry) {
if(entry.$value === null)
{
$scope.error = 'No such entry';
}
else {
$scope.entry = entry;
}
})
.catch(function(error) {
console.error(error);
});
What I want to achieve is to get the category first, and then whether there are some errors or not, get the entry respectively. The data is coming from a Firebase database.
This is kind of working, however I'm not really sure how should I handle the promise when I want to do a next .then and don't nest them one in the other like this:
MyFactory.getCategory().then(function(category) {
if(no category errors) {
MyFactory.getEntry().then(function() {
// ...
});
}
});
For now I'm getting an error in the console (it's type error entry undefined) when for example the category expired or does not exist. I think I did something wrong in the controller when I return but I'm not really sure and hope you can help me dispel all doubts.
So the real question is how should I handle this correctly, to work as expected? Thanks.
Upvotes: 1
Views: 251
Reputation: 2290
You should return a rejected promise when there is an error.
Look at the following example:
MyFactory
.getCategory(categoryId)
.then(function (category) {
if (category.$value === null) {
return $q.reject('The category does not exist');
}
if (new Date() > new Date(category.expireDate)) {
return $q.reject('The category has expired');
}
$scope.category = category;
return MyFactory.getEntry(category.$id, entryId);
})
.then(function (entry) {
if (entry.$value === null) {
return $q.reject('No such entry');
}
$scope.entry = entry;
})
.catch(function (error) {
$scope.error = error;
});
Do not forget to inject $q
to your controller.
Edit
I would also suggest you move the "error logic" to your service, so the controller would always received either data in .then(data => { ... })
or an error string in .catch(error => { ... })
. This would make your controllers cleaner and if you use those service method in a different controller, you would not have to replicate your logic there as well.
Service
return {
getCategory: function(categoryId) {
var ref = firebase.database().ref().child('categories').child(categoryId);
var category = $firebaseObject(ref);
return category.$loaded().then(function() {
if (category.$value === null) {
return $q.reject('The category does not exist');
}
if (new Date() > new Date(category.expireDate)) {
return $q.reject('The category has expired');
}
return category;
});
},
getEntry: function(categoryId, entryId) {
var ref = firebase.database().ref().child('entries').child(categoryId).child(entryId);
var entry = $firebaseObject(ref);
return entry.$loaded().then(function() {
if (entry.$value === null) {
return $q.reject('No such entry');
}
return entry;
});
}
}
Controller
MyFactory
.getCategory(categoryId)
.then(function (category) {
$scope.category = category;
return MyFactory.getEntry(category.$id, entryId);
})
.then(function (entry) {
$scope.entry = entry;
})
.catch(function (error) {
$scope.error = error;
});
Upvotes: 1