异常处理是异步编程的一个难点。

在同步的代码中,异常可以非常easy地通过try catch语句来完毕:

try {
f();
g();
h();
} catch (e) {
// handle any error that occurred...
}

可是在异步代码中,使用一个try代码块将全部可能出现的异常都包含在内是不现实的。实际上,异步API设置不能抛出异常。由于当异常发生时,通常已经没有运行上下文供它抛出了。

全部,在异步API中一般会使用特殊的參数或者错误回调函数来表示异常信息。比方。在Item
61
中提到的下载文件的异常处理能够例如以下进行:

downloadAsync("http://example.com/file.txt", function(text) {
console.log("File contents: " + text);
}, function(error) {
console.log("Error: " + error);
});

可见downloadAsync方法不仅接受了一个作为成功返回响应时的回调函数。同一时候还接受了一个异常回调函数。那么以此类推,在下载多个文件时的异常处理是这种:

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) { // repeated error-handling logic
console.log("Error: " + error);
});
}, function(error) { // repeated error-handling logic
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);

在Node.js中。另一种异常处理API的风格。它会将错误信息作为回调函数的第一个參数。假设没有错误发生,那么该參数的值是null,undefine之类的falsy值。使用这样的方式进行异常处理例如以下所看到的:

function onError(error) {
console.log("Error: " + error);
} downloadAsync("a.txt", function(error, a) {
if (error) {
onError(error);
return;
}
downloadAsync("b.txt", function(error, b) {
// duplicated error-checking logic
if (error) {
onError(error);
return;
}
downloadAsync(url3, function(error, c) {
// duplicated error-checking logic
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(url3, function(error, c) {
if (error) return onError(error);
console.log("Contents: " + a + b + c);
});
});
});

在使用异步API时。忘记对异常进行处理是常常犯的错误。这会让异常信息被忽略掉,从而导致比較糟糕的用户体验。所以在使用异步API时,切记对异常情况进行处理。我想这也是为何在Node.js中,异常信息会被当做回调函数的第一个參数,让开发者不得不面对它。

总结

  1. 避免对异常处理代码进行复制粘贴,将它作为共享的函数是更好的选择。
  2. 确保对异常情况进行处理,避免对异常的忽略。

Effective JavaScript Item 63 注意异步调用中可能会被忽略的异常的更多相关文章

  1. [置顶] Ajax程序:处理异步调用中的异常(使用Asp.Net Ajax内建的异常处理方法)

    无论在Window应用程序,还是Web应用程序以对用户友好的方式显示运行时的异常都是很有必要,尤其对于可能有很多不确定因素导致异常的Web应用程序;在传统的Web开发中,处理异常的方式——设计专门一个 ...

  2. [知识库:python-tornado]异步调用中的上下文控制Tornado stack context

    异步调用中的上下文控制Tornado stack context https://www.zouyesheng.com/context-in-async-env.html 这篇文章真心不错, 非常透彻 ...

  3. Effective JavaScript Item 21 使用apply方法调用函数以传入可变參数列表

    本系列作为Effective JavaScript的读书笔记. 以下是一个拥有可变參数列表的方法的典型样例: average(1, 2, 3); // 2 average(1); // 1 avera ...

  4. Effective JavaScript Item 38 调用父类的构造函数在子类的构造函数

    作为这一系列Effective JavaScript的读书笔记. 在一个游戏或者图形模拟的应用中.都会有场景(Scene)这一概念.在一个场景中会包括一个对象集合,这些对象被称为角色(Actor). ...

  5. Effective JavaScript Item 39 绝不要重用父类型中的属性名

    本系列作为Effective JavaScript的读书笔记. 假设须要向Item 38中的Actor对象加入一个ID信息: function Actor(scene, x, y) { this.sc ...

  6. Effective JavaScript Item 46 优先使用数组而不是Object类型来表示有顺序的集合

    本系列作为Effective JavaScript的读书笔记. ECMAScript标准并没有规定对JavaScript的Object类型中的属性的存储顺序. 可是在使用for..in循环对Objec ...

  7. Effective JavaScript Item 37 认识this的隐式指向

    本系列作为Effective JavaScript的读书笔记. CSV数据通常都会被某种分隔符进行分隔.所以在实现CSV Reader时,须要支持不同的分隔符.那么,非常自然的一种实现就是将分隔符作为 ...

  8. Effective JavaScript Item 10 避免使用with

    本系列作为Effective JavaScript的读书笔记. Item 9:避免使用withkeyword 重点: 设计withkeyword本来是为了让代码变简洁,可是却起到了相反的效果.比方: ...

  9. Effective JavaScript Item 22 使用arguments来创建接受可变參数列表的函数

    本系列作为Effective JavaScript的读书笔记. 在Item 21中,介绍了结合apply方法实现的可变參数列表函数average,它实际上仅仅声明了一个数组作为參数,可是利用apply ...

随机推荐

  1. MikroTik RouterOS虚拟机/实体机安装方法

    一.设置光驱 二.安装RouerOS 按a全选,按i安装,q退出,空格可以选取或取消选取.这里是选择你要安装的组件. 是否要保存原有配置:是否要提交.一路y. 安装好之后按回车重启:之后为这个界面,安 ...

  2. Serial Wire Debug (SWD) Interface -- PSoc5

    PSoC 5 supports programming through the serial wire debug (SWD) interface. There are two signals in ...

  3. UVA 303 Pipe

    点击打开链接 题意: 求光线能达到的最大横坐标 注意光线可以和管道重合 也可以经过转折点 解法: 枚举每种光线是否能通过每个转折点的截面(线段)即可 //大白p263 #include <cma ...

  4. centos7虚拟机(vmware)通过U盘传文件

    centos7虚拟机(vmware)通过U盘传文件 centos7虚拟机安装以后,WINDOWS给CENTOS7传文件,除了在CENTOS7安装SAMBA外,其实通过U盘也是可以的. CENTOS7对 ...

  5. Java加密技术(一)——加密介绍

    from://http://blog.csdn.net/janronehoo/article/details/7590772 如基本的单向加密算法: BASE64 严格地说,属于编码格式,而非加密算法 ...

  6. C++ inline内联函数

    inline 函数避免函数调用的开销 // find longer of two strings const string &shorterString(const string &s ...

  7. CCBAnimationManager

    #ifndef __CCB_CCBANIMATION_MANAGER_H__ #define __CCB_CCBANIMATION_MANAGER_H__ #include "cocos2d ...

  8. unity3d 5.6烘焙教程

    unity5.6是今年发布,作为5.x的最后一个版本,有很多烘焙优势,在此总结一些作为5.x系列完结的笔记这个版本在烘焙上的特点就是增加了渐进光照贴图(Progressive Lightmapper) ...

  9. Android获取actionbar高度和StatusBar高度的方法

    ActionBar: getActionBar().getHeight(); StatusBar: /** * 获取状态栏高度 * * @return */ public static int get ...

  10. 成功让Eclipse更新ADT的方法

    [本文转载自]http://blog.csdn.net/yihui8/article/details/8044426 原文:配置android开发环境eclipse获取ADT获取不到 https:// ...