对异常的捕获和处理是提高程序鲁棒性的一个重要方式,即使在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. 【USACO】Dining

    [题目链接] [JZXX]点击打开链接 [caioj]点击打开链接 [算法] 拆点+网络流 [代码] #include<bits/stdc++.h> using namespace std ...

  2. centos7使用ceph-deploy部署ceph

    准备阶段 准备yum源 删除默认的源,国外的比较慢 yum clean all rm -rf /etc/yum.repos.d/*.repo 下载阿里云的base源 wget -O /etc/yum. ...

  3. PHP 时间戳

    <?php php 获取今日.昨日.上周.本月的起始时间戳和结束时间戳的方法,主要使用到了 php 的时间函数 mktime.下面首先还是直奔主题以示例说明如何使用 mktime 获取今日.昨日 ...

  4. 在xshell中使用Linux语言打开错误提示

    上线项目到服务器后, 有时候有的功能跟本地调试的不一样,这时候就需要设置打开display_errors = On: 首先,cd .. 进入上一级,ll 罗列当前目录,跟home当前目录的有这个usr ...

  5. ERROR (UnicodeEncodeError): 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128

    ERROR (UnicodeEncodeError): 'ascii' codec can't encode characters in position 0-1: ordinal not in ra ...

  6. HTML5/jQuery雷达动画图表 图表配置十分简单

    1.HTML5/jQuery雷达动画图表 图表配置十分简单 之前我们介绍过不少形形色色的HTML5图表了,像这款HTML5折线图表Aristochart是一款很不错的折线图表,这款HTML5 Canv ...

  7. Bootstrap 轻量级后台管理系统模板--ACE使用介绍

    在上一篇基于Bootstrap介绍了一个免费的后台管理模板Charisma UI. 参见链接: 基于Jquery.Bootstrap的后台管理免费UI框架推荐--Charisma UI 今天继续分享一 ...

  8. SQL Server 盛宴系列 webcast

    数据库学习站点,示例,视频 http://technet.microsoft.com/zh-cn/dd722671.aspx

  9. SSIS 事务

    本文摘自:http://www.cnblogs.com/tylerdonet/archive/2011/09/23/2186579.html 在这一个随笔中将介绍在package中如何使用事务来保证数 ...

  10. Android调试之TraceView

    TraceView 在应用运行时,可以使用Debug类打开操作日志记录功能,打开后Android会详细记录应用花在每个线程以及线程的每个函数的调用时间.操作日志记录完毕后,可以使用Android SD ...