Angular 500 error handling doesn't work - angularjs

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');
}]);

Related

How to propagate error in httpProvider responseError interceptor

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.

Angular Js:How to pull factory data to the controller

Hi I am trying to pull my angular js factory data to my controller,
please have a look if there is any issue.
factory.js
.factory('History', ['$http', '$q', function ($http, $q) {
function history () {
// angular.extend(SearchOptions.getDefaults(), params, options);
var deferred = $q.defer();
$http({
method: 'GET',
url: '/res/orders/' + 31536427 + '/history-group'
})
.success(function (res) {
// console.log(res);
})
.error(function (err) {
// TODO error handler
deferred.reject(err);
});
return deferred.promise;
}
return {
history: history
};
}]);
controller.js
.controller('HistoryCtrl', ['$scope', '$state', '$stateParams', 'History', function($scope, $state, $stateParams, History) {
History.history().then(function(res) {
console.log(res);
$scope.history = res.body;
console.log($scope.history);
}, function(err) {
// TODO error handler
console.log(err);
})
.finally(function(err) {
});
}]);
You need to pass the response in the success function in the 'History' factory as below:
.success(function (res) {
// console.log(res);
deferred.resolve(res);
})
The issue with your code is you are not resolving the promise after getting the data in the success callback function. Resolve it as shown below in the .success callback function :
deferred.resolve(res);
Few points to improve your code:
$http service in Angular by default returns a promise. Hence, you don't have to explicitly construct a promise using $q which is an anti pattern (Deferred anti-pattern). Just returning $http object from the service itself will do the
job. Doing return $http() is equivalent to return deferred.promise() in your code.
.success and .error callbacks are deprecated in the latest version(1.6) of AngularJs (Deprecation Notice). The disadvantage of using these is that they are not chainable as they ignore return values. Hence, it is better to use .then instead.
Applying above changes, your service can be refactored to below :
.factory('History', ['$http', function ($http) {
function history () {
return $http({
method: 'GET',
url: '/res/orders/' + 31536427 + '/history-group'
})
.then(successCallback, errorCallback);
}
function successCalback (res) {
return res;
}
function errorCalback (err) {
return err;
}
return {
history: history
};
}]);

AngularJS get value from service function

I have a problem with getting value from service in my controller.
I get the value from API using service:
angular.module('app').factory('service',
['$q', '$rootScope', '$timeout', '$http',
function ($q, $rootScope, $timeout, $http) {
// create user variable
var user = null;
// return available functions for use in the controllers
return ({
isLoggedIn: isLoggedIn,
getUserStatus: getUserStatus,
login: login,
getEmail: getEmail
});
function isLoggedIn() {
if(user) {
return true;
} else {
return false;
}
}
function getUserStatus() {
return $http.get('/user/status')
// handle success
.success(function (data) {
if(data.status){
user = true;
} else {
user = false;
}
})
// handle error
.error(function (data) {
user = false;
});
}
function login(username, password) {
// create a new instance of deferred
var deferred = $q.defer();
// send a post request to the server
$http.post('/user/login',
{username: username, password: password})
// handle success
.success(function (data, status) {
if(status === 200 && data.status){
user = true;
deferred.resolve();
} else {
user = false;
deferred.reject();
}
})
// handle error
.error(function (data) {
user = false;
deferred.reject();
});
// return promise object
return deferred.promise;
}
function getEmail() {
// create a new instance of deferred
var deferred = $q.defer();
$http.get('/email/'+$rootScope.username)
.success(function (data) {
console.log(data);
deferred.resolve();
})
.error(function (data) {
deferred.reject();
})
return deferred.promise;
}
}]);
and I'm trying to get and use value in the controller:
angular.module('app')
.controller('myController', ['$rootScope', '$scope', '$state', '$http', '$q', 'service', function ($rootScope, $scope, $state, $http, $q, service) {
$scope.email;
$scope.getEmail = function() {
// call getEmailFromDB from service
service.getEmail()
// handle success
.then(function (data) {
$scope.email = data; //here I got undefined
console.log($scope.email);
})
// handle error
.catch(function () {
$scope.error = true;
$scope.errorMessage = "wrong#mail.com";
});
};
$scope.getEmail();
}]);
but in the controller there is undefined value.
In my console:
Regarding the documentation of $q, I use then() function in service and controller.
Does anybody know where is the problem?
you forgot to send your result in your service like this
deferred.resolve(data);
In your code you are not returning anything with the promise, to do that you must call deferred.resolve(data) or deferred.reject(data).
Instead of creating a deferred object, you can simply return the $http request.
Example:
function getEmail() {
return $http.get('/email/'+$rootScope.username).then(
function success(data){
console.log(data);
return data;
},
function error(data){
console.error(data);
}
);
}
Also notice that .success() and .error() are deprecated, you should use .then() and pass the success and error functions.

Not able to call service from angularJS controller

I've defined 1 service to fetch the category and controller to call the service.
var req = {
method: 'POST',
url: 'http://localhost/cgi-bin/superCategory.pl',
headers: { 'Content-Type': undefined },
data: { action: 'GET' }
};
sampleApp.factory('SuperCategoryService', ['$http', function ($http){
return {
GetSuperCategories: function () {
return $http(req)
.then(
function(response)
{
if (typeof response.data === 'object')
{
alert ('right');
//return response.data;
}
else
{
alert ('wrong');
// invalid response
//return $q.reject(response.data);
}
},
function(response) {
alert ('again worng');
// something went wrong
//return $q.reject(response.data);
});
}
};
}]);
sampleApp.controller('SuperCategoryController', ['$scope', 'SuperCategoryService', function ($scope, SuperCategoryService){
$scope.SuperCategories = function() {
SuperCategoryService.GetSuperCategories()
.then(function(d) {
alert (d);
if (d != undefined) {
alert ('in');
// Your data should be loaded here
console.log(d.data);
alert (d);
$scope.SuperCategories = d.data;
}
else
{
alert ('Here');
}
})
.error(function(data, status) {
// Errors here
});
}
}]);
Even though i am calling the service in controller, but its not hitting to any of the alert in service. (Not even error case)
What can be the problem? Any help will be highly appreciated.
See this $http documentation.Here you did a mistake in calling method of $http.
sampleApp.factory('SuperCategoryService', ['$http', function ($http){
return {
GetSuperCategories: function () {
return $http.post('http://localhost/cgi-bin/superCategory.pl',{ action: 'GET' });
};
}]);
Please see demo here http://jsbin.com/tahigerube/1/edit
you need to call your $scope.SuperCategories to execute it
...
$scope.SuperCategories();
...

AngularJS Interceptor to Redirect

ExpressJS is sending the following response...
res.send('ItemUploaded');
I'm trying to get AngularJS to see this response via an Interceptor and perform a redirect. Does anyone have sample code where Angular catches a server response (such as my "ItemUploaded") and performs a redirect to a partial (via $location)?
This works fine. I have used it in my application.
var interceptor = function ($q, $location) {
return {
request: function (config) {//req
console.log(config);
return config;
},
response: function (result) {//res
console.log('Repos:');
console.log(result.status);
return result;
},
responseError: function (rejection) {//error
console.log('Failed with', rejection.status, 'status');
if (rejection.status == 403) {
$location.url('/dashboard');
}
return $q.reject(rejection);
}
}
};
module.config(function ($httpProvider) {
$httpProvider.interceptors.push(interceptor);
});
Here is the factory for the interceptor:
.factory('InterceptorService',['$q', '$location', function( $q, $location, $http){
var InterceptorServiceFactory = {};
var _request = function(config){
//success logic here
return config;
}
var _responseError = function(rejection) {
//error here. for example server respond with 401
return $q.reject(rejection);
}
InterceptorServiceFactory.request = _request;
InterceptorServiceFactory.responseError = _responseError;
return InterceptorServiceFactory;
}]);
then register the interceptor:
.config(["$httpProvider", function ($httpProvider) {
$httpProvider.interceptors.push('InterceptorService');
}]);
Every request coming will be passed here.
You can implement a interceptor factory which will redirect if it gets a matching result.
angular
.module('app')
.factory("httpinterceptor", ["$location",
function(location) {
return {
'response': function(response) {
if (response.data === "ItemUploaded") {
location.path("/ItemUploaded")
}
}
}
}
]);

Resources