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

在同步的代码中,异常可以非常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. STM32F1XX devices vector table for EWARM toolchain.

    ;******************** (C) COPYRIGHT 2014 STMicroelectronics ******************* ;* File Name : start ...

  2. hdu4333 Revolving Digits(扩展kmp)

    Revolving Digits Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  3. 向OSG视图Viewer发送消息

    句柄是以下面的方式传递给osgViewer::Viewer的,osgViewer::View.getCamera().setGraphicsContext(osg::GraphicsContext); ...

  4. VS2015 Offline Help Content is now available in 10 more languages!

    https://blogs.msdn.microsoft.com/devcontentloc/2015/10/21/vs2015-offline-help-content-is-now-availab ...

  5. Windows Phone本地数据库(SQLCE):1、介绍(翻译)(转)

    一只大菜鸟,最近要学习windows phone数据库相关的知识,找到了一些比较简短的教程进行学习,由于是英文的,顺便给翻译了.本身英语水平就不好,估计文中有不少错误,如果有不幸读到的童鞋请保持对翻译 ...

  6. ios开发怎样才能做到代码和界面彻底分离,方便换肤?

    设想一下,你现在手底下有N个开发人员,你如何让这些人参与到一个ios开发项目中来?而不是独自一个人完成.

  7. C#编程(六十一)------------LINQ中的扩展方法

    原文链接: http://blog.csdn.net/shanyongxu/article/details/47208401 LINQ中的扩展方法 LINQ中where扩展方法,要想使用,必须导入us ...

  8. 排序算法之归并排序(Mergesort)解析

    转自:http://www.cnblogs.com/ayqy/p/4050452.html   一.归并排序的优缺点(pros and cons) 耗费心思来理解它,总要有个理由吧: 归并排序的效率达 ...

  9. 浴血黑帮第一季/全集Peaky Blinders迅雷下载

    本季第一季Peaky Blinders Season 1 (2013)看点:<浴血黑帮>Peaky Blinders是从战后伯明翰地区走出的一个传奇黑帮家族,时间要追溯到1919年,家族成 ...

  10. Bootstrap table的基本使用总结

    最近在学习BootStrap构建页面,现记录BootStrap table 的一些基本使用如下: HTML文件: <!DOCTYPE html> <html> <meta ...