Reporting an error while using data source with $resource
-
21-12-2019 - |
Domanda
I have created a factory to provide data to my app
myApp.factory('dataRepository', function ($resource) {
return {
getApplicationErrors: function (applicationName) {
return $resource('/api/DataSource/GetApplicationErrors').query();
},
}
I have changed my data access from using $http, $q to use $resource into:
old implementation
var deffered = $q.defer();
$http.get('/api/DataSource/GetApplicationErrors').success(deffered.resolve).error(deffered.reject);
return deffered.promise;
new implementation
$scope.exceptions = dataRepository.getApplicationErrors($routeParams.applicationName);
now in case that there is an error while fetching my data I want to display an error.
So when I had old implementation I had two callback to hook up to and now I am not sure how to implement it. My idea was:
myApp.controller("ErrorListController",
function ErrorListController($scope, dataRepository) {
dataRepository.getApplicationErrors('test')
.$promise
.then(function (data) {
$scope.exceptions = data;
}, function(error) {
$scope.errorMessage = 'Failed to load data from server';
});
});
Question
What is correct way in hooking up to $resource success / fail?
Possible answer
Add call back functions for success and failure, but I do not consider this as solution.
Soluzione
The first thing to consider is why are you changing to $resource
? The $resource
service is supposed to provide a pseudo object-REST mapping. So that you can get hold of objects and collections of objects, which you may wish to modify and save again. If all you want is to have a service that retrieves a collection of errors then it may well be simpler to continue to use $http
.
Second, the way to use $resource
is to call it once inside your service factory function to create a concrete "typed/bound" resource object, which you then return as your service:
myApp.factory('dataRepository', function ($resource) {
return {
getApplicationErrors: $resource('/api/DataSource/GetApplicationErrors')
};
}
In your controller you can inject this to get access to the resource methods. The first parameter of query
is a params
object, which basically gets passed straight through to $http
. So you can do stuff there...
myApp.controller("ErrorListController",
function ErrorListController($scope, dataRepository) {
$scope.errors = dataRepository.getApplicationErrors.query({ params: { appName: 'test' });
};
This will immediately add an empty array to $scope.errors
property. When the response arrives, the resource will fill this array with the results.
If you want to catch errors then you can make use of the $promise
property on the returned object. This gives you access to the raw $http
promise that is being used under the covers:
myApp.controller("ErrorListController",
function ErrorListController($scope, dataRepository) {
$scope.errors = dataRepository.getApplicationErrors.query({ params: { appName: 'test' });
$scope.errors.$promise.then(success, error);
};
Altri suggerimenti
Http interceptors are probably your best bet for wrapping all response errors. It's essentially a way to wrap all of your http calls through angular. You're going to want to do something like this:
.config(function($httpProvider) {
$httpProvider.interceptors.push('MyInterceptor');
})
.service('MyInterceptor', function($q, $injector) {
return {
responseError: function(error) {
// Maybe you want to persist to database?
$http = $injector.get('$http');
$http.post('/log/my/error', error);
//... Notify the user of the error here or add logic to dynamically propagate to the user
alert("ERROR: " + error);
// continue promise chain
$q.reject(error);
}
};
});
Documentation can be found here. In the http interceptors section.