exception handling - form - Práctica recomendada para el manejo de excepciones de aplicaciones en AngularJS
error handler angular 5 (3)
¿Cuál es su opinión para crear una función centralized error handling function
para su aplicación?
así que cada vez que ocurría un error con su rasgadura de frontend (llamadas angulares, API, ...) se ejecutaba, por lo que no need to write
su error handling
every time
error handling
así que aquí está mi código
(function () {
''use strict'';
angular
.module(''app'')
.factory(''$exceptionHandler'', ExceptionHandler);
ExceptionHandler.$inject = [''$injector'']; //for minification
function ExceptionHandler($injector) {
var $log, sweetAlert, $translate;
return function exceptionHandler(exception, cause) {
// Add DI here to prevent circular dependency
$log = $log || $injector.get(''$log'');
sweetAlert = sweetAlert || $injector.get(''sweetAlert''); //19degrees.ngSweetAlert2
$translate = $translate || $injector.get(''$translate'');
// $loggerService = $loggerService || $injector.get(''$loggerService'');
var title, message;
title = $translate.instant(''General error title'');
message = $translate.instant(''General error message'', { exceptionMessage: exception.message });
sweetAlert.error(title, message);
$log.error(exception, cause);
// loggerService.logErrorsToBackend(exception, cause);
};
}
})();
No estoy seguro si este enfoque se considera una mejor práctica, pero espero que lo ayude.
Actualmente estoy explorando posibles métodos para manejar excepciones de toda la aplicación en AngularJS.
Una de las cosas que realmente queríamos evitar era envolver varias partes de la aplicación en bloques de try / catch anidados, pero manejar las cosas limpiamente, es decir lanzar una excepción en respuesta a una promesa.
- ¿Alguien ha cubierto este tema anteriormente y tiene alguna recomendación?
- Cualquier sugerencia sobre cómo recoger excepciones en servicios así como en controladores / directivas. (Consulte a continuación - la transmisión funciona bien, pero solo si puede adjuntar un oyente a un alcance).
Progreso hasta el momento
Algunos objetivos de diseño cortos:
- Permita que las excepciones de una parte de la aplicación se manejen en otro lugar, o posiblemente en varios lugares (es decir, ''mostrar notificación de error al usuario'', ''desactivar widget'').
- Proporcionar administración central de las condiciones de error comunes, es decir, iniciar sesión en el servidor, mostrar notificaciones al usuario, redirigir para iniciar sesión.
- Permita que se emitan excepciones desde los controladores, directivas, servicios, etc.
- Eventualmente permita mensajes localizados.
La inclinación actual de mi equipo es escribir un servicio para manejar excepciones, que expondría una gama de llamadas simples:
exceptionService.warn(''exception_token'');
exceptionService.crit(''another_exception_token'');
Este servicio luego formateará un objeto ''excepción'' y lo transmitirá desde el ramoscopio. Esto permitiría a un controlador predeterminado observar las difusiones y aplicar acciones predeterminadas, así como permitir que las escuchas personalizadas se establezcan en otros ámbitos, que podrían manejar condiciones más específicas, es decir, desactivar una parte de la IU.
var exception = {
token: ''exception_token'',
severity'': ''crit''
};
// broadcast exception
$rootScope.$broadcast(
''application_exception'',
exception
);
Estaba pensando en lo mismo recientemente, y se me ocurrió que cuando se trata de un buen manejo de errores en JavaScript, es irrelevante qué marco está utilizando, Angular en otra cosa. Hace poco escribí uno de esos manejadores de errores para un proyecto AngularJS, pero lo hice de una manera que puede usarse en cualquier marco.
Aquí está el código completo. Puede usarlo directamente o modificar según sus necesidades ...
/*
Factory errorFact is to simplify error handling and reporting in other objects.
It supports detailed error output as a text string and into the browser''s console.
Usage example:
A function that supports return of an error object would have the following declaration
as its very first line:
var e = errorFact.create("objectName.funcName", arguments);
- in this declaration we specify the full object + method name as the first string parameter,
- and as the second parameter we pass javascript''s reserved variable called arguments, which
provides reference to all of the function''s parameters for logging.
When an error occurs, the function would return:
return e.error("Error description text");
- this line will create and return a complete error context.
When a function that supports return of an error object makes a call into another
function that also supports the error context, then it can return the nested error
result by passing the embedded error to the current error object instead of the error
text.
Example:
var e = errorFact.create("objectName.funcName", arguments);
var data = callAnotherFunc(...); // calling a function that support an error object;
if(data.isError){ // If an error was triggered;
return e.error(data); // return that error from the current context;
}
The top-level code that calls an error-returning function would do verification
and if an error occurred, log all its details into console (typically).
Example:
var data = getData(...);
if(data.isError){
data.log(); // Output all the error details into the browser''s console;
}
*/
"use strict";
app.factory("errorFact", function(){
return {
// creates a new error context;
create: function(method, args){
var result = {
// initiates and returns the error context;
error: function(msg){
this.info.isError = true;
if(msg.isError){
this.info.details.caller = msg;
}else{
this.info.details.msg = msg;
}
return this.info;
},
info:
{
isError: false,
details: {},
log: function(){
if(this.isError){
console.error(this.format());
}
},
// formats complete error details into a text string;
format: function(){
if(this.details.caller){
var txt = this.details.caller.format();
txt += "/nCALLER: " + this.details.method + "(" + this.formatArguments() + ")";
return txt;
}
if(this.details.method){
return "Error calling " + this.details.method + "(" + this.formatArguments() + "): " + this.details.msg;
}else{
return this.details.msg;
}
return "";
},
// formats function argument details into a text string;
formatArguments: function(){
if(!this.details.args){
return "";
}
var params = "";
for(var i = 0;i < this.details.args.length;i ++){
if(params.length > 0){
params += ",";
}
var p = this.details.args[i];
if(p === undefined){
params += "undefined";
}else{
if(p === null){
params += "null";
}else{
if(typeof(p) == "object"){
params += "Object";
}else{
params += p;
}
}
}
}
return params;
}
}
};
if(method){
result.info.details.method = method;
}
if(args){
result.info.details.args = args;
}
return result;
}
}
});
A continuación se muestra una fábrica que muestra cómo se usa:
"use strict";
app.factory(''moduleFact'', [''errorFact'', function(errorFact){
return {
// Locates existing module and expands its key Id references
// into corresponding object references:
// - If ''hintGroupId'' is present, property ''hints'' is added from
// the corresponding hint group.
// - If ''repModules'' is present, properties ''question'' and ''refs''
// are added.
// On success, return the expanded module object.
// On failure, returns an error object.
//
// NOTE: Currently supports only the first value in repModules.
expandModule: function(moduleData, moduleId){
var e = errorFact.create("moduleFact.expandModule", arguments);
if(!moduleData || !moduleData.modules || !moduleId){
return e.error("Invalid parameters passed");
}
var mod = this.findModule(moduleData, moduleId);
if(mod.isError){
return e.error(mod);
}
var src = mod;
if(mod.repModules){
var repId = mod.repModules[0];
if(!repId){
return e.error("Invalid repModules encountered");
}
///////////////////////////////////////
// temporary check to throw a warning:
if(mod.repModules.length > 1){
console.warn("Multiple values in property repModules: " + JSON.stringify(mod.repModules) +
", which is not supported yet (only the first value is used)");
}
///////////////////////////////////////
src = this.findModule(moduleData, repId);
if(src.isError){
return e.error(src);
}
}
if(src.question){
mod.question = src.question;
}else{
return e.error("Question not specified");
}
if(src.refs){
mod.refs = src.refs;
}
if(src.hintGroupId){
var hg = this.findHintGroup(moduleData, src.hintGroupId);
if(hg.isError){
return e.error(hg);
}
mod.hints = hg.hints;
}
return mod; // needed extra: expand attribute repModules
},
// Expands all the modules and returns the data;
expandAllModules: function(moduleData){
var e = errorFact.create("moduleFact.expandAllModules", arguments);
if(!moduleData || !moduleData.modules){
return e.error("Invalid parameters passed");
}
for(var i = 0;i < moduleData.modules.length;i ++){
var result = this.expandModule(moduleData, moduleData.modules[i].id);
if(result.isError){
return e.error(result);
}
}
return moduleData;
},
// Locates and returns module by its Id;
findModule: function(moduleData, moduleId){
var e = errorFact.create("moduleFact.findModule", arguments);
if(!moduleData || !moduleData.modules || !moduleId){
return e.error("Invalid parameters passed");
}
for(var i = 0;i < moduleData.modules.length;i ++){
if(moduleData.modules[i].id == moduleId){
return moduleData.modules[i];
}
}
return e.error("Module with Id = " + moduleId + " not found");
},
// Locates and returns Hint Group by its Id;
findHintGroup: function(moduleData, hintGroupId){
var e = errorFact.create("moduleFact.findHintGroup", arguments);
if(!moduleData || !moduleData.hintGroups || !hintGroupId){
return e.error("Invalid parameters passed");
}
for(var i = 0;i < moduleData.hintGroups.length;i ++){
if(moduleData.hintGroups[i].id == hintGroupId){
return moduleData.hintGroups[i];
}
}
return e.error("Hint Group with Id = " + hintGroupId + " not found");
}
}
}]);
Entonces, cuando tenga dicha fábrica en su lugar, su código de alto nivel, como en un controlador, simplemente registrará cualquier problema como se muestra en el siguiente ejemplo:
"use strict";
app.controller(''standardsCtrl'', [''$scope'', ''moduleFact'', function($scope, moduleFact){
var data = ...//getting data;
var mod = moduleFact.expandAllModules(data);
if(mod.isError){
mod.log(); // log all error details into the console;
}else{
// use the data
}
});
}]);
Puede anular el $ exceptionHandler para pasar las excepciones a su propio servicio central por excepciones, pero el $ exceptionHandler parece que solo recibe las excepciones lanzadas desde sus controladores, directivas, etc. ... pero no por las excepciones originadas desde llamadas ajax. . Para esas excepciones, puede implementar un interceptor como el descrito en esta página:
EDITADO: El enlace está muerto permanentemente.
Enlace de Archive.org