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

在同步的代码中,异常可以非常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. spring cloud 学习(9) - turbine stream无法在eureka注册的解决办法

    turbine是啥就不多解释了,初次接触的可以移步spring cloud 学习(4) - hystrix 服务熔断处理 拉到最后看一下,turbine stream默认情况下启动成功后,eureka ...

  2. LayoutParams继承于Android.View.ViewGroup.LayoutParams(转)

    LayoutParams相当于一个Layout的信息包,它封装了Layout的位置.高.宽等信息.假设在屏幕上一块区域是由一个Layout占领的,如果将一个View添加到一个Layout中,最好告诉L ...

  3. mysql函数的使用

    最近总感觉sql语句不对劲,所以就看了一些官方文档发现了一些以前没有注意的函数:感觉在查询的时候可以用得上,毕竟是内置函数,用起来效率应该会好一些的: FIND_IN_SET(str,strlist) ...

  4. MyEclipse使用总结——MyEclipse中配置WebLogic12c服务器

    MyEclipse中配置WebLogic12c服务器的步骤如下: [Window]→[Preferences],如下图所示: 找到WebLogic的配置,如下图所示:

  5. How To: Implement a Major Upgrade In Your Installer

    When creating an .msi-based installer, you are strongly encouraged to include logic that supports Wi ...

  6. eclipse配置问题汇总

    问题1:fatjar安装出现故障 问题描写叙述:由于要打包包括第三方jar包的工程,需下载eclipse插件.一般下载地址:http://sourceforge.net/projects/fjep/ ...

  7. sql语句中having的作用是?

    HAVING对由sum或其它集合函数运算结果的输出进行限制.比如,我们可能只希望看到Store_Information数据表中销售总额超过1500美圆的商店的信息,这时我们就需要使用HAVING从句. ...

  8. firedac数据集和字符串之间相互转换

    firedac数据集和字符串之间相互转换 /// <author>cxg 2018-12-20</author> unit DatasetString; interface u ...

  9. 读取 android sys/下的信息

    读取 android sys/下的信息 https://github.com/ruw/Internet-Services-projects/tree/master/OffloadPredictor/l ...

  10. Java web实时进度条整个系统共用(如java上传、下载进度条、导入、导出excel进度条等)

    先上图: 文件上传的: 2017-05-04再次改进.在上传过程中用户可以按 Esc 来取消上传(取消当前上传,或者是全部上传)... 2019-03-26更新进度条显示体验 从服务器上压缩下载: 从 ...