How to propagate error in httpProvider responseError interceptor - angularjs

We have the following code in place for form validation:
$scope.masterModel.$save().then(function (data) {
$scope.masters.data.push(data);
$location.path('/master/edit/' + data.id);
}).error(function (data) {
$scope.errors = data.data;
});
Now we added code to generally catch code 500 server errors on a global level to the app.js
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(function ($injector) {
return {
'responseError': function (rejection) {
// do something on error
if (rejection.status === 500) {
var angularModalService= $injector.get("ModalService");
angularModalService.showModal({
templateUrl: "templates/common/session.html",
controller: "ModalController"
}).then(function (modal) {
modal.element.modal();
modal.close.then(function (result) {
if (result) {
}
});
});
}
}
};
});
}]);
As soon as we add this code, the error callback in the first code does not work anymore.
I think we have to somehow propagate the error in the responseError callback, but how does that work?
AngularJS Version is 1.5.11

You need to "reject the rejection" in the interceptor and return it in order for the error to be propagated:P
var app= angular.module('MyApp', []);
app.controller('Controller', function($scope, $http, $q) {
$http.get("http://www.example.invalid/fake.json")
.then(function(response) {
console.log("success");
}, function(error) {
console.log("controller error handler");
});
});
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(function ($injector, $q) {
return {
'responseError': function (rejection) {
console.log("interceptor error handler");
// do something on error
if (rejection.status === 500) {
// do something...
}
return $q.reject(rejection);
}
};
});
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp">
<div ng-controller="Controller">
</div>
</div>
As you can see, I added the line
return $q.reject(rejection);
at the end of your interceptor. You can check the console and see that now both messages are logged.

Related

Angular 500 error handling doesn't work

I have service which make post request and returns a data.
app.service('flagService', ['$http', function ($http) {
this.getData = function (r, c) {
return $http.post('http://localhost:8080/api/flag', { row: r, column: c }).then(function (data) {
return data;
})
}
}]);
And somewhere in the controller
flagService.getData(row, column).then(function () {
console.log('it works')
})
But api can also return 500 status code. In this case I get "posssible unhandled rejection..." in the console. Now I would like to make simple alert() which will open when 500 error is returned. I've tried many, many solutions including second function, .catch(), .error().
app.service('flagService', ['$http', function ($http) {
this.getData = function (r, c) {
return $http.post('http://localhost:8080/api/flag', { row: r, column: c }).then(function (data) {
return data;
}, function (error) {
console.log(error)
}).catch(function () {console.log('error')}).error(function() {console.log('error')})
}
}]);
But I still can't hadle error. Any solution? Thanks!
You can use interceptors for global error handling, responseError will be called whenever request is resolved with a rejection.
.factory('myInterceptor', ['$q', '$location', '$injector', function ($q, $location, $injector) {
return {
response: function (response) {
return response || $q.when(response);
},
responseError: function (rejection) {
if (rejection.status === 500) {
console.log('http 500 response')
}
return $q.reject(rejection);
}
}
}])
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
}]);

Circular dependency angularjs

can anyone tell me where is the circular dependency in the following code?
var homeApp = angular.module("homeApp",['ngAnimate', 'ui.bootstrap']);
'use strict';
homeApp.factory('AdminDashboardService', ['$http', '$q', function($http, $q){
return {
'response': function(response) {
// do something on success
console.log("Yes Command comes here");
return response;
},
getAllHolidays: function(monthYearArrayForHolidayList) {
console.log("For full list of holidays list length: "+monthYearArrayForHolidayList.length);
var isMonthly="no";
return $http.get('/tasktrac/holiday/getHoliday/isMonthly/'+isMonthly+'/'+monthYearArrayForHolidayList)
.then(
function(response){
return response.data;
},
function(errResponse){
//console.error('Error while fetching holiday');
return $q.reject(errResponse);
}
);
},
}]);
homeApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('AdminDashboardService');
}]);
I am stuck at this point please do me a favour in resolving this issue.
This is the Error I got on the browser
Please click here to see error
Thank you..!!
A $http interceptor could not declare $http as a dependency!
Inject $injector:
homeApp.factory('AdminDashboardService', ['$injector', '$q', function($injector, $q){
return {
'response': function(response) {
// do something on success
console.log("Yes Command comes here");
return response;
},
getAllHolidays: function(monthYearArrayForHolidayList) {
console.log("For full list of holidays list length: "+monthYearArrayForHolidayList.length);
var isMonthly="no";
return $injector.get("$http").get('/tasktrac/holiday/getHoliday/isMonthly/'+isMonthly+'/'+monthYearArrayForHolidayList)
.then(
function(response){
return response.data;
},
function(errResponse){
//console.error('Error while fetching holiday');
return $q.reject(errResponse);
}
);
},
}]);

Set header to all $resource methods

I'm using ng-resource in Angular to access a RESTful API. I created a simple factory to perform this.
.factory('Bookmark', function($resource){
return $resource('http://bookmarks-angular.herokuapp.com/api/bookmarks/:id');
})
And in the controller I used Bookmark.query:
.controller('MainController', function($scope, Category, Bookmark){
$scope.name = 'Carl';
Category.getAll(function(data){
$scope.categories = data.categories;
$scope.currentCategory = data.categories[0];
$scope.bookmarks = Bookmark.query();
});
})
I need to use Bookmark.save and Bookmark.removeand also a token in the Authorization header. Searching this is the approach I have to use:
$resource('url/to/json', {}, {
get: {
method: 'GET',
headers: { 'something': 'anything' }
}
});
But it works just to the get method and I want to use send the token in every $resource methods. I do not want to overwrite all the methods just to send this header. Is there any other solution?
You can create an httpInterceptor, something like this from the angular docs:
$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
return {
'request': function(config) {
// add headers
return config;
}
}
https://docs.angularjs.org/api/ng/service/$http
This might help you in creating interceptor.
http://ramanshankar.blogspot.in/2015/11/angularjs-http-interceptor.html
var app = angular.module('simpleDirective', []);
app.config(['$httpProvider', function($httpProvider){
$httpProvider.interceptors.push('httpInterceptor');
}]);
app.controller("DemoController", ['$rootScope','demoService', function($rootScope, demoService){
$rootScope.message = [];
$rootScope.message.push("In Demo Controller");
demoService.functionOne();
}]);
app.service("demoService", ['$http','$rootScope',function($http, $rootScope){
this.functionOne = function(){
$http.get("temp.html")
.success(function(data){
$rootScope.message.push(data);
})
.error(function(data){
$rootScope.message.push("Demo Service Error: "+data);
});
}
}]);
app.factory("httpInterceptor", function(){
return{
'request': function(config) {
alert("request");
return config;
},
'requestError': function(rejection) {
alert("request error");
return "Request error";
},
'response': function(response) {
alert("response");
return response;
},
'responseError': function(rejection) {
alert("response error");
return "response error";
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="simpleDirective">
<div ng-controller="DemoController">
<h2>AngularJS Interceptor Example</h2>
<div ng-repeat="msg in message">
<div style="padding:5px;background:lightgrey;border:1px solid black;margin-bottom:10px;">{{msg}}</div>
</div>
</div>
</div>

$q.reject does not rethrow the exception within $http.get().then().catch()

I'm dealing with code like this:
return promise.then(function(url) {
return $http.get(url, data);
}).then(function (response) {
return response.data;
}).catch(function (response) {
return $q.reject(response);
});
All I want to do is to reject the promise in the "catch" block so the exception is logged by my custom implementation of $exceptionHandler.
According to my understanding of the documentation, the line below is supposed to rethrow the exception but it is not doing it. Thus, $exceptionHandler never handlers the exception:
return $q.reject(reason); // why isn't it rethrowing?
Chances are I'm misunderstanding the documentation.
The error is re throwing - as controller can catch error and displays it.
angular.module('app', [])
.controller('app', function($scope, service) {
$scope.error = {}
service
.load('foo')
.catch(function(error) {
angular.extend($scope.error, {
reason: error
});
});
})
.service('service', function($http, $q) {
var promise = function promise() {
var d = $q.defer();
d.reject('some reason')
return d.promise;
}();
this.load = function(url) {
return promise
.then(function() {
return $http.get(url);
})
.then(function(response) {
return response.data;
})
.catch(function(reason) {
return $q.reject(reason);
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app'>
<div ng-controller='app'>error: {{ error.reason }}</div>
</div>

Issue getting $rootScope injected into config of Angular?

I am doing:
myApp.config([
'$httpProvider', '$rootScope', function($httpProvider, $rootScope) {
$httpProvider.interceptors.push(function($q) {
return {
responseError: function(rejection) {
var defer;
defer = $q.defer();
if (rejection.status === 401) {
$rootScope.$broadcast('api-error', rejection);
}
defer.reject(rejection);
return defer.promise;
},
response: function(response) {
var defer;
defer = $q.defer();
console.log(response);
if (response.status === 401) {
$rootScope.$broadcast('api-error', response);
defer.reject(response);
} else {
defer.resolve(response);
}
return defer.promise;
}
};
});
}
]);
But I get an error that it cannot find $rootScope. I read this answer and it says to do some weird global variable stuff, which seems like a bad idea.
So how can I redirect to another route upon a 401 status?
Inject $rootScope in the interceptor, not in the configuration function:
myApp.config([
'$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(function($q, $rootScope) {
...

Resources