管理异步编程的一个是错误处理。同步代码中只要使用try语句块包装一段代码很容易一下子处理所有的错误。

try{
f();
g();
h();
} catch(e){
//这里用来下得出现的错误
}

try语句块

但对于异步的代码,多步的处理通常会被分隔到事件队列的单独轮次中,因此,不可能将它们包装在一个try语句块中。事实上异步的API甚至根本不可能抛出异常,因为,当一个异步的错误发生时,没有一个明显的执行上下文来抛出异常!相反,异步的API倾向于将错误表示为回调函数的特定参数,或使用一个附加的错误处理回调函数。例如,一个涉及下载文件的异步API可能会有一个额外的回调函数来处理网络错误。

downloadAsync('http://cnblogs.com/wengxuesong',function(text){
console.log('file contents:'+text);
},function(error){
console.log('error:'+error);
});

如果下载多个文件,可以像62条讲的,使用回调函数嵌套起来。

downloadAsync('a.txt',function(a){
downloadAsync('b.txt',function(b){
downloadAsync('c.txt',function(c){
console.log('Contents:'+a+b+c);
},function(error){
console.log('error:'+error);
});
},function(error){
console.log('error:'+error);
});
},function(error){
console.log('error:'+error);
});

上面代码上,每一步的处理都使用了相同的错误处理逻辑,然而我们在多个地方重复了相同的代码。在编程领域里,应该努力坚持避免重复代码。通过共享作用域中定义一个错误处理的函数,将重复代码抽象出来。

function onError(error){
console.log('Error:'+error);
}
downloadAsync('a.txt',function(a){
downloadAsync('b.txt',function(b){
downloadAsync('c.txt',function(c){
console.log('Contents:'+a+b+c);
},onError);
},onError);
},onError);

如果使用工具函数downloadAllAsync将多个步骤合并到一个复合的操作中,那么,只需要提供一个错误处理的回调函数。

downloadAllAsync(['a.txt','b.txt','c.txt'],function(abc){
console.log('Contents:'+abc[0]+abc[1]+abc[2]);
},function(error){
console.log('Error:'+error);
});

回调函数错误参数

另一种错误处理API的风格是Node.js平台使用的。该风格只需要一个回调函数,该回调函数的第一个参数如果有错误发生就表示一个错误。否则就是一个假值,比如null。对于这类API,我们可以定义一个通用的错误处理函数,需要使用if语句来控制每个回调函数。

function onError(error){
console.log('Error:'+error);
}
downloadAsync('a.txt',function(error,a){
if(error){
onError(error);
return;
}
downloadAsync('b.txt',function(error,b){
if(error){
onError(error);
return;
}
downloadAsync('c.txt',function(error,c){
if(error){
onError(error);
return;
}
console.log('Contents:'+a+b+c);
});
});
});

程序员通常会放弃if语句而使用大括号结构跨越多行的约定,以使得错误处理更简洁、更集中。

function onError(error){
console.log('Error:'+error);
}
downloadAsync('a.txt',function(error,a){
if(error)return onError(error);
downloadAsync('b.txt',function(error,b){
if(error)return onError(error);
downloadAsync('c.txt',function(error,c){
if(error)return onError(error);
console.log('Contents:'+a+b+c);
});
});
});

也可以使用一个抽象合并步骤来帮助消除重复

var filenames=['a.txt','b.txt','c.txt'];
downloadAllAsync(filenames,function(error,abc){
if(error){
console.log('Error:'+error);
return;
}
console.log('Contents:'+abc[0]+abc[1]+abc[2]);
});

try...catch语句和在异步API中典型的错误处理逻辑的一个实际差异是,try语句使得定义一个"捕获所有"的逻辑很容易导致程序员难以忘怀整个代码区的错误处理。而上面给出的异步API,非常容易忘记在进程的任意一步提供错误处理。这将导致错误被丢弃。忽视错误处理的程序会令用户非常沮丧:应用程序出错时没有任何的反馈。类似的,默认的错误不好调试。因为没有提供问题来源的线索。最好是做好防御,即使用异步API需要警惕,确保明确地处理所有的错误状态条件。

提示

  • 通过编写共享的错误处理函数来避免复制和粘贴错误处理代码

  • 确保明确地处理所有的错误条件以避免丢弃错误

最新文章

  1. sybase学习
  2. WOW: 宏
  3. java配置自动任务,定期执行代码
  4. php大力力 [025节] 来不及学习和分类的,大力力认为有价值的一些技术文章合集(大力力二叔公)(2015-08-27)
  5. @media_screen
  6. 在Visual Studio 2010中使用DSL Tool特定领域开发 开篇
  7. PHP中的循环while、do...while、for、foreach四种循环。
  8. 逆向iOS SDK -- _UIImageAtPath 的实现(SDK 5.1)
  9. LeetCode_Single Number II
  10. Freemodbus 1.5
  11. 带着新人简单看看servlet到springmvc
  12. CROS+node-basis+ajax
  13. WinAPI 字符及字符串函数(15): CharNext、CharPrev
  14. Iview Modal 点击确定就关闭,我想禁止关闭该怎么办呢?
  15. 《Thinking In Java》---第四版 练习题答案
  16. 常对象与this指针
  17. (转)CSS书写规范、顺序
  18. mybatis问题: There is no getter for property named 'equipmentId' in 'class java.lang.String'
  19. DataGrid中Combox bingding string
  20. Oracle常用单行函数(原创)

热门文章

  1. Eclispe怎么给工作空间下的项目分组
  2. CSS3是怎么实现全景特效?
  3. maven创建web工程,并导入到eclipse中
  4. Java中的try,catch,finally
  5. django基于正则的url匹配
  6. sqlmap用户手册详解(转)
  7. linux查看主机端口进程命令
  8. in_array支持第三个参数,强制对数据类型检测
  9. 大量查询SQL语句 实例
  10. 【iCore3 双核心板_FPGA】实验十八:基于单口RAM的ARM+FPGA数据存取实验