I just start learning AngularJS. I don't know where to find a tutorial to arm myself with a knowledge of dealing an exception in the following code:
angular.module('myApp').controller('MyController', ['$scope', '$stateParams', '$modalInstance', 'entity', 'MyEntity',
function($scope, $stateParams, $modalInstance, entity, MyEntity) {
...
var onSaveFinished = function (result) {
$scope.$emit('myApp:myEntityUpdate', result);
$modalInstance.close(result);
};
$scope.save = function () {
MyEntity.save($scope.myEntity, onSaveFinished); <-- an exception can occur on this line
I need to catch any exception on an Ajax call and display an error accordingly on the html file. I have tried using .catch and .error without a luck of catching an exception.
Can someone point a direction on where to learn a knowledge on this topic.
Try to use $exceptionHandler service. That's what Angular's docs say:
Any uncaught exception in angular expressions is delegated to this service. The default implementation simply delegates to $log.error which logs it into the browser console.
To add your own exception handling, you should override the normal action of $exceptionHandler (example in docs).
Related
I'm overriding the Angular $exceptionHandler to do some custom logging of exceptions. Unfortunately, my Logging service uses $http for logging, which is dependent on $exceptionHandler. Any thoughts on a pattern that would resolve my circular reference and still allow me to log via $http?
Here is my Service overriding $exceptionHandler:
angular.module('dashboard').factory('$exceptionHandler', ['$log', 'Logging',
function($log, Logging){
return function globalErrorHandler(exception, cause){
var itemToLog = new logItem('dashboard', 'General Error', exception.message + ": " + exception.stack);
Logging.logEvent(itemToLog);
$log.warn(exception, cause);
}
}]);
and my custom Logging service:
angular.module('dashboard').factory('Logging', ['$http', function($http) {
return {
logEvent: function(item){
$http.post('/api/loggingservice/event', item)
.success(function(data){
return data;
}).
error(function(data){
console.log('error logging event: '+JSON.stringify(data));
});;
}
};
}]);
And the error message I receive is:
angular.min.js:6 Uncaught Error: [$injector:cdep]
https://docs.angularjs.org/error/$injector/cdep?p0=$http%20%3C-%20Logging%20%3C-%20$exceptionHandler%20%3C-%20$rootScope%20%3C-%20$http%20%3C-%20UserManagement%20%3C-%20Menus
$exceptionHandler is used by other core services that $http depends on. This makes injecting $http or a service that depends on $http impossible, because this results in circular dependency.
A usual recipe to avoid CD in Angular 1 is using $injector.get(...) instead of injecting a service in service factory/constructor function. However, the developer should be aware why it is done and what it is going on there.
Doing something like
function($log, $injector){
var Logging = $injector.get('Logging');
return function globalErrorHandler(exception, cause){ ... }
}
won't break circular dependency, because $exceptionHandler is eagerly instantiated by core services which $http depends on, which Logging depends on.
On the other hand,
function($log, $injector){
return function globalErrorHandler(exception, cause){
var Logging = $injector.get('Logging');
...
}
}
will work because this way Logging is lazily instantiated. This will result in executing $injector.get(...) on each handler call. But this is fine, since $injector.get(...) has no performance impact and can be called multiple times, especially in non-critical places.
So I am trying to figure out the easiest route for authentication with AngularJS and Google Plus. I have worked with angular-google-plus and it is great, spits back all my user information. I Then wanted to get back if a user is registered or not when they come to a new page or controller in my project. So I found this post which basically said the project needs to extend the api. Fine, but he implements a watcher that, when executed in my Controller works for the gapi, but when it checks for the gapi.auth it returns undefined. My console.log tells me both of them are there and are objects. Here is my controller code:
.controller('LoginController', ['$scope', '$state', '$window', '$http','$rootScope', 'GooglePlus', function ($scope, $state, $window, $http, $rootScope, GooglePlus) {
var checkGoogleReady = $rootScope.$watch(function() {
console.log(gapi);
$scope.login = function() {
GooglePlus.login().then(function (authResult) {
console.log(authResult);
GooglePlus.getUser().then(function (user) {
console.log(user);
});
}, function (err) {
console.log(err);
});
};
}])
So the stuff inside the login() function all works, returns everything I need. But outside it, it fails to get gapi.auth and never changes after that. I feel like it checks, finds gapi, then changes gapi.auth and then tries to wait for another change, never getting the gapi.auth. Here is a picture of the console:
So you can see all 3 objects actually have the auth property on them. So I am not sure why the gapi.auth is coming back undefined.
got to work with angular JS on learning how angular works.
I am trying controllers, directvies and services in an example project:
[http://codepen.io/anon/pen/PpOERy][1]
Actually I got this error if I try to use my service on clicking the button:
TypeError: Cannot read property '*****' of undefined
Whats my failure?
Regards n00n
You forgot to annotate your service, little typo ;)
Your code
myApp.controller('MainCtrl', ['$scope', function ($scope, CalculatorService) {
Correct code
myApp.controller('MainCtrl', ['$scope', 'CalculatorService', function ($scope, CalculatorService) {
As a bit of background - I have created a simple interceptor to handle 401's in angular. All the data in the application is retrieved from the server using breeze.
Below is the 401 interceptor I am using
app.factory(serviceId, ['$q', '$location', function ($q, $location) {
var authInterceptorServiceFactory = {};
var _responseError = function (rejection) {
if (rejection.status === 401) {
$location.path('/login');
}
return $q.reject(rejection);
}
authInterceptorServiceFactory.responseError = _responseError;
return authInterceptorServiceFactory;
}]);
Whenever I attempt to navigate to a page that requires the user to be authenticated it works as expected and I am redirected to the login page. My console however is littered full of errors and it looks rather unprofessional, is there anyway to get rid of or suppress these errors?
I don't think Breeze is doing this. Search breeze.debug.js and you'll find no references to the console or a logging component. When a $http call returns anything but a 200, breeze rejects the promise so that layers up the line can decide what to do. In many cases it delegates back to Angular. All of this is evident when you read the breeze code.
I suspect that you need to configure Angular to suppress this console output.
Do update us when you figure it out.
I've been struggling with this all morning. I'm trying to call a Service from within my config($httpprovider). I've read a lot of people explaining that Services are not yet available during config. I get that, but my service should only be called from within the interceptor, which is at runtime.
I found a semi-solution that manually injected the Service manually like below, but it's not working for me, since it seems a completely new instance of the Service is being created, and I want to keep using the same instance throughout the app (since it stores a messageQueue array). Any suggestions?
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(function ($q) {
return {
'responseError': function (rejection) {
//responses 300 and up are errors
//Manually inject service from the myServices module, since it is not yet known when .config is called
var $injector = window.angular.injector(['myServices']);
var MessageService = $injector.get('MessageService');
MessageService.setMessage("We were unable to load all necessary data. We're terribly sorry! Please try reloading this page or contact us if the problem isn't solved.");
}
};
});
}])
You can register your interceptor as a service using a factory, according to angularjs 1.2.2 documentation, so it should be provided with the right dependencies, using the following syntax :
.config(['$httpProvider', function ($httpProvider) {
$provide.factory('myHttpInterceptor', ['MessageService', function (MessageService) {
return {
'responseError': function (rejection) {
//responses 300 and up are errors
MessageService.setMessage("We were unable to load all necessary data. We're terribly sorry! Please try reloading this page or contact us if the problem isn't solved.");
}
};
}]);
$httpProvider.interceptors.push('myHttpInterceptor');
}]);