JS模块间错误隔离
问题背景:
页面中有多个功能模块,怎么在一个模块出了问题之后,保证其它模块的正常工作。
上面的差不多就是面试官的原话了,姑且称之为模块间错误隔离问题
第一反应是动态按需加载代码,用户操作发生后再加载对应模块代码,面试官(后文简称:对面)说所有模块代码都是在页面载入时加载的,不允许动态加载。
第二反应是error事件处理器return true,对面问确定这样做能隔离错误吗?不确定,好吧。。接着想
第三反应是try-catch,对面问怎么个try-catch法?说用try把各个模块包裹起来啊,也可以用工厂。。哦,那你写个工厂给我看看。。然后就傻傻地写了个这:
function getModule(type){
switch(type){
case Consts.type1 :
return function(){
try{
Modules[type]();
}catch(err){
// fix
}
};
break;
...
}
}
看对面不是很满意,就又补充说也可以把case里的匿名方法提出来,作为一个包装工具,但就只能做统一错误处理,而用这个可以针对模块做不同的错误处理,各有各的好处。。。对面勉强点头
之后对面沉默了很久,2分钟吧,有些忐忑,就弱弱地问是不是上个问题的答案不是您想要的?对面说:还行,用异常处理包起来确实可以。。
但感觉和对面想要的答案还是有些差距,所以有了本文
一.子问题
从上面的面试过程能找出几个子问题:
- 动态按需加载能不能隔离错误?
- error事件处理器return true能不能隔离错误?
- 闭包能不能隔离错误?如果把各个模块都放在各自的闭包里,像YUI一样,有用吗?
- try-catch怎么用才比较好?一定要用工厂吗?
先给出测试结果:
- 动态加载能隔离错误,因为在没有try-catch的情况下,错误的影响范围(作用域?)是script标签或者整个外部js文件,也就是说,如果script标签中或者外部js文件的第n行发生了错误,那么第n行后面的代码都不会再执行了。。。所以通过插入script标签来动态加载,确实能隔离错误
- 处理error事件不能隔离错误,让error事件处理器返回true只能抑制浏览器报错,没有什么恢复断点的作用,对程序员而言并没有实际意义
- 闭包不能隔离错误,但可以隔离影响,YUI的每个模块都被放在闭包中,这样可以更方便地管理作用域,避免模块间的相互影响
- try-catch这样用比较好:
function getSafeFun(fun){ // 集中处理错误
return function(){
try{
fun();
}catch(err){
if (err instanceof TypeError) {
// 类型不匹配
}
else if (err instanceof ReferenceError) {
// 引用错误
}
else{
// ...
}
}
};
} function getSafeFun2(fun, errHandler){ // 针对函数处理错误
return function(){
try{
fun();
}catch(err){
errHandler();
}
};
}上面的是基础包装工具,还可以进一步封装,添一个好用的外观(Facade):
// 配置数据
var Modules = {};
Modules.mod1 = {
desc : "模块1",
method : errorFun
};
Modules.mod2 = {
desc : "模块2",
method : fun
}; /*
* 统一模块调用接口
*/
function use(moduleName, errHandler){
if (typeof errHandler === "function") {
getSafeFun2(Modules[moduleName].method, errHandler)();
}
else {
getSafeFun(Modules[moduleName].method)();
}
}直接用use传入模块名和可选的错误处理器就可以隔离错误了,感觉好多了
不需要工厂,工厂是根据给定的参数返回对应类型的东西,而我们所做的不过是用try包裹了一下而已,和工厂没多大关系,感觉和装饰、外观的关系更大一点。。当然,重要的是好用,而不是一定要用什么模式
二.测试验证
1.动态按需加载能不能隔离错误?
测试代码:
<script type="text/javascript">
script1
alert(1);
</script> <script type="text/javascript">
alert(2);
</script>
运行结果:2,script标签能够隔离错误,所以动态加载也能隔离错误
2.error事件处理器return true能不能隔离错误?
测试代码:(在head里的script标签中插入如下代码)
window.onerror = function(e){
return true; // 不报错
}
运行结果:不报错,也不会alert 1,对程序员而言没什么作用,不能隔离错误
3.闭包能不能隔离错误?如果把各个模块都放在各自的闭包里,像YUI一样,有用吗?
测试代码:
// 闭包1
(function(){
closure
alert(1);
})();
// 闭包2,无法执行,因为闭包1出错了
(function(){
alert(2);
})();
运行结果:没有alert任何东西,只要闭包1和2在同一个script标签或者同一个外部js文件中,闭包2都会因为闭包1出错而无法执行,所以闭包不能隔离错误
4.try-catch怎么用才比较好?
当然不能强制要求所有编码人员都在调用模块的时候用try包裹,我们至少得有一个包装工具,像这样的:
function getSafeFun(fun){ // 集中处理错误
return function(){
try{
fun();
}catch(err){
if (err instanceof TypeError) {
// 类型不匹配
}
else if (err instanceof ReferenceError) {
// 引用错误
}
else{
// ...
}
}
};
}
function getSafeFun2(fun, errHandler){ // 针对函数处理错误
return function(){
try{
fun();
}catch(err){
errHandler();
}
};
}
/* 测试 */
function errorFun(){
errorFunction
alert(1);
}
function fun(){
alert(2);
}
getSafeFun(errorFun)();
getSafeFun(fun)();
现在有了getSafeFun()和getSafeFun2(),可以少写一点try了,但还是得要求所有编码人员自己看情况调用才能隔离错误,还是不科学,应该再添点什么
// 配置数据
var Modules = {};
Modules.mod1 = {
desc : "模块1",
method : errorFun
};
Modules.mod2 = {
desc : "模块2",
method : fun
}; /*
* 统一模块调用接口
*/
function use(moduleName, errHandler){
if (typeof errHandler === "function") {
getSafeFun2(Modules[moduleName].method, errHandler)();
}
else {
getSafeFun(Modules[moduleName].method)();
}
} /* 测试 */
use("mod1");
use("mod1", function(){
alert("fix");
});
use("mod2");
现在就比较人性化了,只留一个入口,只需要告诉编码人员以前的模块调用方式过时了,现在的新API是use即可
三.结论
抛开问题本身,上面的所有测试结果可以归纳如下:
- 一个script标签中的代码发生错误,不会导致页面其它script标签内代码不执行
- window.onerror事件处理器中return true只能让浏览器不报错,而后面的代码不会再执行了
- 闭包对模块间错误隔离无益,但可以隔离模块间影响
- try-catch可以隔离错误,有错误隔离效果
参考资料
JS模块间错误隔离的更多相关文章
- js 页面间的通信
看了一下公司原来的代码,原页面ajax post返回一个页面完整的HTML,然后再打开一个新页面并输出ajax返回的所有代码到新页面上,在新页面上以表单提交的形式实现重定向. 任凭我想了半天也没想出来 ...
- Node.js权威指南 (10) - Node.js中的错误处理与断言处理
10.1 使用domain模块处理错误 / 272 10.1.1 domain模块概述 / 272 10.1.2 创建并使用Domain对象 / 274 10.1.3 隐式绑定与显式绑定 / 276 ...
- 如何发布一个自定义Node.js模块到NPM(详细步骤)
咱们闲话不多说,直接开始! 由于我从没有使用过MAC,所以我不保证本文中介绍的操作与MAC一致. 文章开始我先假定各位已经在window全局安装了Node.js,下面开始进行详细步骤介绍: 本文本着, ...
- 【 js 模块加载 】深入学习模块化加载(node.js 模块源码)
一.模块规范 说到模块化加载,就不得先说一说模块规范.模块规范是用来约束每个模块,让其必须按照一定的格式编写.AMD,CMD,CommonJS 是目前最常用的三种模块化书写规范. 1.AMD(Asy ...
- Node.js 模块
稳定性: 5 - 锁定 Node 有简单的模块加载系统.在 Node 里,文件和模块是一一对应的.下面例子里,foo.js 加载同一个文件夹里的 circle.js 模块. foo.js 内容: va ...
- 【 js 模块加载 】【源码学习】深入学习模块化加载(node.js 模块源码)
文章提纲: 第一部分:介绍模块规范及之间区别 第二部分:以 node.js 实现模块化规范 源码,深入学习. 一.模块规范 说到模块化加载,就不得先说一说模块规范.模块规范是用来约束每个模块,让其必须 ...
- 如何发布一个自定义Node.js模块到NPM(详细步骤,附Git使用方法)
咱们闲话不多说,直接开始! 由于我从没有使用过MAC,所以我不保证本文中介绍的操作与MAC一致. 文章开始我先假定各位已经在window全局安装了Node.js,下面开始进行详细步骤介绍: 本文本着, ...
- 七、CommonJS规范和Note.js模块概念的介绍
在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护.为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多 ...
- Developer - 如何自我保证Node.js模块质量
组里正在做SaaS产品,其中一些模块(Module)是Node.js实现,这里我们主要使用Node.js实现Web Server来提供服务. 在做SaaS项目之前,组里的开发模式是传统的Deverlo ...
随机推荐
- COM的永久接口
COM的永久接口
- android开发 如何调用SO
java package com.example.callsodemo; import android.R.integer; import android.R.string; import andro ...
- 关于Eclipse项目中加入jquery.js文件报错(missing semicolon)问题
在使用Eclipse3.7及以后的版本的时候,加入jQuery文件会报错(missing semicolon),文件中会显示红色小X,虽然这个错误并不会影响项目的运行,但是这个却会大大的影响到开发人员 ...
- Javascript类型
Javascript 有两中类型:原始类型和对象类型. 原始类型包括:数字,字符串,布尔值,null和undefined.其余的都是对象类型. 原始类型 数字.Javascript采用IEEE754标 ...
- LightOJ 1285 - Drawing Simple Polygon (几何,极角排序)
1285 - Drawing Simple Polygon PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: ...
- Linux系统编程-防止僵尸进程产生的常用方法
1.父进程调用wait函数或waitpid函数回收子进程. 2.让init进程去处理子进程回收工作,代码中加上"signal(SIGCHLD, SIG_IGN)"这句话.
- JSP如何保存页面上众多的复选状态
一.描述: 最近写的一个问题管理模块,录入问题时需要选择客户(也就是那些客户存在这些问题),当保存完问题后,再次编辑问题时,如何从数据库里读取上次选中的客户并展示位勾选状态呢?问题表cust_ques ...
- Collection List Set和Map用法与区别
labels:Collection List Set和Map用法与区别 java 散列表 集合 Collection 接 口的接口 对 象的集合 ├ List ...
- 嵌入式web服务器
要实现在PC上通过网页控制连接到嵌入式开发板的相机. 限于开发板的环境,不能选择appche等大型web服务器,选择了boa. 要想pc端跨平台,那就不能用ActiveX控件,如果仅在windows平 ...
- HDU2243_考研路茫茫――单词情结
给出一些词根,问你有多少种长度为L的串包含至少一个词根. 去年就在敲这个题了,今年才敲出来,还是内牛满面之中... 要求包含至少一个的情况,需要求出所有的情况,减去一个都没有的情况就可以了. 对于给出 ...