异常处理 – 在AngularJS中应用程序异常处理的推荐做法

我目前正在探索可能的方法来处理AngularJS中的应用程序范围的异常。

我们真正想要避免的事情之一是在嵌套的try / catch块中包装应用程序的多个部分,但干净地处理事情 – 即响应promise而抛出异常。

>有没有人覆盖这个问题,并有任何建议?
>关于如何在服务以及控制器/指令中提取异常的任何建议。 (见下面 – 广播工作确定,但只有当你可以附加监听器到范围)。

进展到目前为止

几个短设计目标:

>允许来自应用程序的一部分的异常在其他地方 – 或者可能多个地方(即“向用户显示错误通知”,“禁用窗口小部件”)处理。
>提供常见错误状况的中央管理 – 即日志到服务器,向用户显示通知重定向登录
>允许从控制器,指令和服务等抛出异常。
>最终允许本地化的消息。

我的团队目前的倾向是编写一个服务来处理异常,这将暴露一系列简单的调用

exceptionService.warn('exception_token');

exceptionService.crit('another_exception_token');

这个服务然后格式化一个“异常”对象,并从rootscope广播。这将允许默认处理程序监视任何广播和应用默认操作,以及允许在其他范围中设置自定义侦听器,这可以处理更具体的条件,即禁用部分UI。

var exception = {
    token: 'exception_token',severity': 'crit'
};

// broadcast exception
$rootScope.$broadcast(
'application_exception',exception
);
我最近一直在想,并且它发生在我,当谈到一个良好的错误处理在JavaScript,它是不相关的哪个框架,你使用,Angular在别的东西。我最近为一个AngularJS项目写了一个这样的错误处理程序,但我做了一个方式,它可以在任何框架中使用。

这里是完整的代码。您可以直接使用它,或修改为您的需要…

/*
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;
        }
    }
});

下面是一个显示如何使用它的工厂:

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

所以,当你有这样的工厂,你的高级代码,如在控制器中只会记录任何问题,如下面的例子所示:

"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
        }
    });

}]);

相关文章

AngularJS 是一个JavaScript 框架。它可通过 注:建议把脚本放在 元素的底部。这会提高网页加载速度,因...
angluarjs中页面初始化的时候会出现语法{{}}在页面中问题,也即是页面闪烁问题。出现这个的原因是:由于...
AngularJS 通过被称为指令的新属性来扩展 HTML。AngularJS 指令AngularJS 指令是扩展的 HTML 属性,带有...
AngularJS 使用表达式把数据绑定到 HTML。AngularJS 表达式AngularJS 表达式写在双大括号内:{{ expres...
ng-repeat 指令可以完美的显示表格。在表格中显示数据 {{ x.Name }} {{ x.Country }} 使用 CSS 样式为了...
$http是 AngularJS 中的一个核心服务,用于读取远程服务器的数据。读取 JSON 文件下是存储在web服务器上...