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

在同步的代码中,异常可以非常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. 华为S5300系列交换机限制特定IP可以登录Web

    针对Web管理可能有如下需求: 1.限制某个特定IP允许访问Web 2.默认修改80端口访问 那么针对上面的设置可以有效杜绝而已Web密码暴力破解,增强交换机安全等. 实现: 1.限制特定IP登录We ...

  2. 【转】Java类成员变量默认初始化规则

    一个变量作为类成员使用的时候,如果没有被初始化,java会为其分配默认值: -------------------------------------------------------------- ...

  3. 使用36-pin的STM32输出VGA, VGA output using a 36-pin STM32

    使用36-pin的STM32输出VGA 手头上有个项目需要通过单片机来控制将图像显示在LCD上,在网上搜了一阵子,发现都是使用的FPGA做的, 开始自己对FPGA不是很熟,一直在用的也是ARM系列的, ...

  4. Timer-triggered memory-to-memory DMA transfer demonstrator

    http://www.efton.sk/STM32/bt.c // Timer-triggered memory-to-memory DMA transfer demonstrator for STM ...

  5. 未经处理的异常:System.Net.Sockets.SocketException: 以一种访问权限不允许的方式做了一个访问套接字的尝试

    报错:未经处理的异常:System.Net.Sockets.SocketException: 以一种访问权限不允许的方式做了一个访问套接字的尝试 → 尝试以"管理员身份"运行程序, ...

  6. NGINX前端代理TOMCAT取真实客户端IP

    nginx前端代理tomcat取真实客户端IP 使用Nginx作为反向代理时,Tomcat的日志记录的客户端IP就不在是真实的客户端IP,而是Nginx代理的IP.要解决这个问题可以在Nginx配置一 ...

  7. 关于面试总结11-selenium面试题

    前言 面试web自动化必然会问到selenium,问selenium相关的问题定位是最基本的,也是自动化的根本,所以面试离不开元素定位问题. 之前看到招聘要求里面说"只会复制粘贴xpath的 ...

  8. osx升级到10.10后,使用pod install报错解决的方法

    先看下网上的解决方法例如以下: 先依照这个文章做:http://blog.csdn.net/dqjyong/article/details/37958067 大概过程例如以下: Open Xcode ...

  9. End2endIT

    "C:\Program Files\Java\jdk1.8.0_112\bin\java" -ea -Didea.test.cyclic.buffer.size=1048576 & ...

  10. 《Java性能优化权威指南》

    <Java性能优化权威指南> 基本信息 原书名:Java performance 原出版社: Addison-Wesley Professional 作者: (美)Charlie Hunt ...