对异常的捕获和处理是提高程序鲁棒性的一个重要方式,即使在javascript/nodejs等看似“很难写出bug”的弱类型语言里,异常捕获处理仍至关重要,这主要是因为:

1.在一个代码块里,如果程序运行过程中自动、或主动(new Error/Exception)生成异常/错误后,若不主动去try...catch该异常,这个异常会逐层抛出,直至主程序,系统会按照框架默认方式处理该异常。

2.在逐层抛出异常的过程中,每层代码块异常点之后的程序不会再被执行,除非进行try...catch异常处理。

我们看几个简单的例子来验证一下。

(() => {
try{
(()=>{
nonExistentFunction();
console.log('c');
})();
console.log( 'b' );
}catch(e){
console.log( e );
}
})();
console.log( 'a' );

打印结果:

即,打印了最外层的catch内的异常处理信息和主程序接下来的部分,根据1,2可知,如果匿名函数最外层没有进行try...catch处理的话,a也不会被打印出来。

这意味着,即使是“很难写出bug”的javascript也可能因为一个小小的异常导致整个程序歇菜!try...catch则是保证主干按流程执行完毕的关键实现。

容易被误处理的异步异常

在nodejs等异步IO密集场景,经常用异步回调函数来处理IO操作结果——不管是正确的数据还是异常Error,但此时的try...catch怎么来写?

const fs = require('fs');
try{
fs.readFile( __dirname+'/15_fs1.js',(err,data) =>{
if( err ){
throw err;
}else{
console.log( data );
}
} );
}catch(err){
console.log( 'an error occured!',err );
} console.log( 'hhh' );

在文件不存在的情况下,按照try..catch的作用,我们认为应该在catch里捕捉到异常并执行异常处理语句,即打印“an error occured!XXX”;但实际结果呢?

即,异常最后并未被目前缩写的catch所捕获,而是最终被系统级捕获并按照框架方式打印出了错误信息,这是为什么呢?主要是因为try...catch是代码块,是被同步解析的,当代码执行到try后,开始读文件操作,等待异步执行结果,但catch语句是紧接着try进行的,它并不会等待异步执行的结果,因此,当执行到catch的时候,回调里的throw error还没执行呢,当然catch不到了,主程序继续解析执行直到打印出'hhh'。随后当异步会调离throw err的时候没有catch可以捕获的到,只能层层抛出到最外层,由框架来捕获和执行。

理解上述内容后,就该想到问题的关键点是try...catch的执行ticker与回调函数ticker不同步的问题,解决的办法也很简单,同步try...catch与callback函数的时钟—将try..catch放在callback里面。

正确的代码示例:

const fs = require('fs');

fs.readFile( __dirname+'/15_fs1.js',(err,data) =>{
try{
if( err ){
throw err;
}else{
console.log( data );
}
}catch(e){
console.log( e );
}
} );
console.log( 'hhh' );

打印结果:

19年要在使用新框架写好业务逻辑的基础上,提高自己输出代码的鲁棒性,经常去分析、反思可能出现异常的模块并进行forecast error的捕获处理,进一步提高自己的代码水平。

——学无止境,保持好奇。May stars guide your way.

用好js与nodejs中的try...catch的更多相关文章

  1. 原声js实现nodejs中qs模块中的parse和stringfiy方法

    function stringify(obj, sep, eq) { sep = sep || '&'; eq = eq || '='; let str = ""; for ...

  2. Node.js学习笔记(二) --- CommonJs和Nodejs 中自定义模块

    一. 什么是 CommonJs? JavaScript 是一个强大面向对象语言,它有很多快速高效的解释器. 然而, JavaScript标准定义的 API 是为了构建基于浏览器的应用程序.并没有制定一 ...

  3. 在python中调用js或者nodejs

    在python中调用js或者nodejs要使用PyExecJs第三方包. pip install pyexecjs 示例代码 >>> import execjs >>&g ...

  4. 在Nodejs中如何调用C#的代码

    最近需要在Nodejs中用到C#的代码,从网上了解到可以采用Edgejs来实现Nodejs与C#的代码交互, 直接复制网上的代码运行总是出各种错,填了不少坑,现在把自己的案例代码大致整理一下,方便以后 ...

  5. NodeJS中的异步I/O、事件驱动

    nodejs的主要特点是单线程.异步I/O.事件驱动.让我们先大概了解一下这些名词的意思. 单线程 单线程是任务按照顺序执行的,并且每次只执行一个任务,只有前面的任务执行完成以后,后面的任务才执行.在 ...

  6. 探讨Nodejs中的作用域问题。

    在JS中有全局作用域和函数作用域,而在Nodejs中也自己的作用域,分为全局作用域(global)和模块作用域. js作用域: 以前学js的时候我们的全局对象是window,如: var a = 10 ...

  7. nodejs中exports与module.exports的实践

    只要是在nodejs中写自己的文件模块就少不了会遇到module.exports和exports的使用,看别人的代码大多都会使用“module.exports=exports=<对象/函数等&g ...

  8. 详细讲解nodejs中使用socket的私聊的方式

    详细讲解nodejs中使用socket的私聊的方式 在上一次我使用nodejs+express+socketio+mysql搭建聊天室,这基本上就是从socket.io的官网上的一份教程式复制学习,然 ...

  9. nodejs中常用加密算法

    在常用的nodejs+express工程中,为了安全在登录及表单传输时,应该都需进行加密传输,目前个人常用到的加密方式有下列几种: 1.Hash算法加密: 创建一个nodejs文件hash.js,输入 ...

随机推荐

  1. 基于aspectj实现AOP操作的两种方式——注解方式

  2. Vue.js style(内联样式)

    Vue.js style(内联样式) 我们可以在 v-bind:style 直接设置样式: <div id="app"> <div v-bind:style=&q ...

  3. poj1639顶点度限制生成树

    题目:http://poj.org/problem?id=1639 对根的度数有限制的最小生成树: 先忽略根,跑最小生成树,得到几个连通块,再一一与根连上: 然后在限制内用根连出去的边来使生成树更小, ...

  4. mysql 入门 1

    连接mysql服务器 mysql -h localhost -u username -ppasswd 1.查看服务器存在的库 show databases; 2.创建数据库 create databa ...

  5. 双重检查锁实现单例(java)

    单例类在Java开发者中非常常用,但是它给初级开发者们造成了很多挑战.他们所面对的其中一个关键挑战是,怎样确保单例类的行为是单例?也就是说,无论任何原因,如何防止单例类有多个实例.在整个应用生命周期中 ...

  6. 四、Chrome开发者工具详解(4)-Profiles面板

    摘自: http://www.cnblogs.com/charliechu/p/6003713.html

  7. 网页中控制ActiveX插件高度

    说明:IE窗口中承载了一个ActiveX插件,试图使该插件充填窗口(自适应窗口的高度.宽度),且不出滚动条. 承载插件的代码如下: <body>    <form id=" ...

  8. HrrpClient使用

    使用HttpClient获取网页内容的过程 1.创建一个CloseableHttpClient类的实例: 2.使用这个实例执行HTTP请求,得到一个HttpResponse的实例: 3.最后,通过Ht ...

  9. 3.19 YARN HA架构及(RM/NM) Restart讲解

    一.ResourceManager HA ResourceManager(RM)负责跟踪集群中的资源,以及调度应用程序(例如,MapReduce作业). 在Hadoop 2.4之前,ResourceM ...

  10. Node.js 自定义模块

    Node.js内置多个模块,也可以使用第三方模块,今天学习一下如何使用自己定义的模块 在同级目录下定义两个js文件 第一个:custom1.js "use strict"; fun ...