详解JavaScript错误捕获

目录
  • 一、基本使用与逻辑
  • 二、特性
  • 三、错误对象
  • 四、较好的catch和throw策略
  • 五、Promise的错误处理
  • 六、性能损耗​

一、基本使用与逻辑

使用

try{
    //code....
}catch(err){
    //error handling
}finally{
    //no matter what happens in the try/catch (error or no error), this code in the finally statement should run.
}

逻辑

二、特性

try...catch 仅适用于运行时错误,解释阶段错误无法正常工作

try{
    {{{{{{{
}catch(err){
    console.error(err)
}
//引擎在‘parse-time'出错,导致无法理解代码,因此无法捕捉

try...catch 只能同步工作

try{
    setTimeout(function(){
        undefinedVariable;
    },1000)
}catch(err){
    console.error(err)
}
//setTimeout的回调函数执行时,引擎已经离开try...catch结构

finally 能让try块中的return语句失效

function test(){
  try {
    return 1;
  } catch(error) {
    return 2;
  } finally {
    return 3;
  }
}
console.log(test());
//3

三、错误对象

当程序发生error,js内部会生成一个包含error细节的对象,该对象会被作为参数传进catch

对于所有内置错误,错误对象具有两个主要属性

  • name 错误类型
  • message 文本类型的错误信息
  • stack (非标准属性)发生错误时的调用栈信息,主要用于调试
try {
  lalala; // error, variable is not defined!
} catch (err) {
  alert(err.name); // ReferenceError
  alert(err.message); // lalala is not defined
  alert(err.stack); // ReferenceError: lalala is not defined at (...call stack)

  // Can also show an error as a whole
  // The error is converted to string as "name: message"
  alert(err); // ReferenceError: lalala is not defined
}

理论上,我们可以throw任何东西作为错误对象,但最好的习惯是throw一个具有name,message的对象,以便和内置错误对象保持兼容

番外:内置的错误对象

对象 含义
ReferenceError 引用未定义变量时触发
SyntaxError 使用不合法的语法结构时触发
TypeError 值得类型非预期时触发
URIError 错误使用全局URI函数如encodeURI()、decodeURI()等时触发
RangeError 对Array构造函数使用错误的长度值,对Number.toExponential()、Number.toFixed()或Number.toPrecision()使用无效数字等
EvalError 全局函数eval()中发生的错误

四、较好的catch和throw策略

​ catch错误不单单是为了防止程序挂掉,更重要的目的是方便调试,找bug,所以对错误的处理策略,稍微可以体现出码者的优雅性

​ 俗话说的好,码者,人恒雅也,尽量遵循一个原则,catch只处理自己知道的错误

举个梨子

let json = '{ "age": 30 }';
try{
  let user = JSON.parse(json);
  alert( user.name );
} catch (err) {
  console.error('JSON Error:'+err);
}

上述例子的catch策略能保证程序正常,因为catch块能catch内部所有的错误,无论是JSON.parse出错还是user.name不存在报错,都能被catch到,但两种错误都用同一种打印是不利于调试的,写成下面这样会好一点

let json = '{"age":30}'
try{
  let user =  JSON.parse(json);
  alert(user.name)
}catch(err){
   if(err instanceof SyntaxError){
       console.error('JSON Error:'+err);
   }
   else throw err;
}

每个catch块处理自己知道得,可能会出现得错误,就是说,编程人员在编程的时候,catch那些预料到的错误,而将可能自己没料到的错误抛到外面。

五、Promise的错误处理

​ 众所周知,Promise是会吞掉error的,因为promise的实现就在内部对所有error进行了捕获,且捕获到的error不是向外抛出(外指promise之外),而是沿着链找到最近的onreject回调传入,所以promise的错误处理只有两种办法

  1. 设置onreject回调
  2. 全局捕获

举个栗子

try{
    new Promise((resolve,reject)=>{
        throw new Error('promise error')
    }).catch(()=>{
        //错误在最近的onreject回调被捕获
        console.error(err);
    })
}catch(err){
    //永远不会执行,promise吞掉error
    console.error(err);
}

另外需要注意,无论是执行者函数(executor)和还是 promise 的处理程序(handler),内部发生的错误统统吞掉,相当于被隐式catch,error会自动找到最近的onreject回调传进去

try{
    new Promise((resolve,reject)=>{
        resolve();
    }).then(()=>{
        throw new Error('promise then error');
    }).catch((err){
        console.error(err);
    })
}catch(err){
    //地球毁灭之前都不会执行
    console.error(err)
}

同理,在错误找到onreject传进去之前,经过的then注册的onfulfilled回调统统失效,直到找到onreject回调,处理之后,onreject回调之后的onfulfilled回调才正常

try {
    new Promise((resolve, reject) => {
        throw new Error('promise error')
    }).then((ret) => {
        //错误没有处理,失效
        console.log('then1:' + ret)
    }).catch((err) => {
        //错误处理了,后序正常
        console.error(err);
        return 'handled'
    }).then((ret) => {
        //正常执行
        console.log('then2' + ret);
    })
} catch (err) {
    //同样的,人类毁灭之前都不会执行
    console.error(err)
}

// Error:promise error
//then2handled

那整条链一个catch都没设置会怎么样呢?

那这个error就会击穿地心,一直穿透到全局,根据宿主环境的不同触发不同的全局事件,比如说浏览器中会触发 unhandledrejection事件,node环境中也会触发unhandledRejection事件,一般会对这事件进行监听,再显示信息给编程人员或者用户

番外1:chromium / v8 / v8 / 3.29.45 的 Promise内部错误捕捉

番外2:async/await错误捕捉

六、性能损耗​

After V8 version 6 (shipped with Node 8.3 and latest Chrome), the performance of code inside try-catch is the same as that of normal code. ------ 爆栈网

(稍微测了一下,相差无几)

以上就是详解JavaScript错误捕获的详细内容,更多关于JavaScript 错误捕获的资料请关注我们其它相关文章!

(0)

相关推荐

  • javascript 初学教程及五子棋小程序的简单实现

    一.JavaScript简介 JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能. 二.hbulider工具的使用 1) hbulider的特点: 1.飞快的编码速度 2.HBuilder直接创建移动App,打包为ios或Android原生安装包 3.HTML5语法.HTML5+

  • Extjs学习过程中新手容易碰到的低级错误积累

    1.下载extjs的安装包,里面没有.msi文件,看好多的安装方法说都有这个.msi文件,但是我在官方下载的解压缩后没有,以为不能用.说明一下,我用的开发工具是visualstudio 2008,其实根本不用安装,直接解压缩后放到创建的网站项目的目录下,然后再也页面添加extjs的引用就行啦. 2.extjs的引用的错误. <script type="text/javascript" src="extjs/adapter/ext/ext-base.js">

  • JavaScript语句错误throw、try及catch实例解析

    try 语句测试代码块的错误. catch 语句处理错误. throw 语句创建自定义错误. finally 语句在 try 和 catch 语句之后,无论是否有触发异常,该语句都会执行. JavaScript 抛出(throw)错误 当错误发生时,当事情出问题时,JavaScript 引擎通常会停止,并生成一个错误消息. 描述这种情况的技术术语是:JavaScript 将抛出一个错误. JavaScript try 和 catch try 语句允许我们定义在执行时进行错误测试的代码块. cat

  • JS错误处理与调试操作实例分析

    本文实例讲述了JS错误处理与调试操作.分享给大家供大家参考,具体如下: JavaScript 错误 - throw.try 和 catch try 语句测试代码块的错误. catch 语句处理错误. throw 语句创建自定义错误. finally 语句在 try 和 catch 语句之后,无论是否有触发异常,该语句都会执行. JavaScript try 和 catch try 语句允许我们定义在执行时进行错误测试的代码块. catch 语句允许我们定义当 try 代码块发生错误时,所执行的代

  • JavaScript初学者容易犯的几个错误

    目录 前言 混淆 undefined 和 null 混淆数字相加和字符串拼接 return 语句换行问题 用 return 跳出 forEach 循环 总结 前言 抛开 JavaScript 语言设计层面的问题不说,毕竟它是 Brendan Eich 当年用短短十天时间设计出来的,有点缺陷也是在所难免.作为开发者,我们该怎样避免一些常见的低级错误呢?本文就列举几个常见错误,看看你有没有似曾相识. 混淆 undefined 和 null JavaScript 中的undefined和null都可用

  • 7个你应该知道的JS原生错误类型

    概述 从浏览器控制台到运行 Node.js的终端,我们到处都会看到错误.本文的重点是概述我们在js开发过程中可能遇到的错误类型. 提示:良好的错误提示会导致快速而无痛的发展经历与缓慢而痛苦的发展经历之间的区别.在编写可重用的代码时,请确保自己在编写清晰易懂的错误处理代码. 1. RangeError 当数字超出允许的值范围时,将会抛出此错误. 例如 const l = console.logconst arr = [90,88] arr.length=90**99 我们有一个数组,带有两个元素的

  • JS常见错误(Error)及处理方案详解

    1. 错误的类型 Error: 所有错误的父类型 错误的子类型包括: ReferenceError: 引用的变量不存在 TypeError: 数据类型不正确的错误 RangeError: 数据值不在其所允许的范围内 SyntaxError: 语法错误 常见的内置错误: (1)ReferenceError: 引用变量不存在 console.log(a) //ReferenceError: a is not defined (2)TypeError: 数据类型不正确 var b = {} b.xxx

  • JavaScript初学者必看“new”

    译者按: 本文简单的介绍了new, 更多的是介绍原型(prototype),值得一读. 原文:JavaScript For Beginners: the 'new' operator 译者: Fundebug 为了保证可读性,本文采用意译而非直译.另外,本文版权归原作者所有,翻译仅用于学习 当你使用new的时候,会: 1.创建一个新的空对象: 2.将this绑定到该对象: 3.添加一个名为__proto__的新属性,并且指向构造函数的原型(prototype): 4.返回该this对象. 如果你

  • JavaScript将DOM事件处理程序封装为event.js 出现的低级错误问题

    将 DOM 0级事件处理程序和DOM2级事件处理程序 IE事件处理程序封装为eventUtil对象,达到跨浏览器的效果.代码如下: var eventUtil = { // 添加事件句柄 addEventHandler:function (element,type,handler) { if (element.addEventListener) { element.addEventListener(type, handler,false); }else if(element.attachEven

  • 详解JavaScript错误捕获

    目录 一.基本使用与逻辑 二.特性 三.错误对象 四.较好的catch和throw策略 五.Promise的错误处理 六.性能损耗​ 一.基本使用与逻辑 使用 try{ //code.... }catch(err){ //error handling }finally{ //no matter what happens in the try/catch (error or no error), this code in the finally statement should run. } 逻辑

  • 万字详解JavaScript手写一个Promise

    目录 前言 Promise核心原理实现 Promise的使用分析 MyPromise的实现 在Promise中加入异步操作 实现then方法的多次调用 实现then的链式调用 then方法链式调用识别Promise对象自返回 捕获错误及 then 链式调用其他状态代码补充 捕获执行器错误 捕获then中的报错 错误与异步状态的链式调用 将then方法的参数变成可选参数 Promise.all方法的实现 Promise.resolve方法的实现 finally方法的实现 catch方法的实现 完整

  • 详解JavaScript中的4种类型识别方法

    具体内容如下: 1.typeof [输出]首字母小写的字符串形式 [功能] [a]可以识别标准类型(将Null识别为object) [b]不能识别具体的对象类型(Function除外) [实例] console.log(typeof "jerry");//"string" console.log(typeof 12);//"number" console.log(typeof true);//"boolean" console

  • 详解JavaScript 事件流

    事件 HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件.想要知道这些事件是在什么时候进行调用的,就需要了解一下"事件流"的概念. 事件流 事件流描述的就是从页面中接收事件的顺序.而早期的IE和Netscape提出了完全相反的事件流概念,IE事件流是事件冒泡,而Netscape的事件流就是事件捕获. 事件流类别 事件冒泡 即从下至上,从目标触发的元素逐级向上传播,直到win

  • 详解JavaScript中的链式调用

    链模式 链模式是一种链式调用的方式,准确来说不属于通常定义的设计模式范畴,但链式调用是一种非常有用的代码构建技巧. 描述 链式调用在JavaScript语言中很常见,如jQuery.Promise等,都是使用的链式调用,当我们在调用同一对象多次其属性或方法的时候,我们需要多次书写对象进行.或()操作,链式调用是一种简化此过程的一种编码方式,使代码简洁.易读. 链式调用通常有以下几种实现方式,但是本质上相似,都是通过返回对象供之后进行调用. this的作用域链,jQuery的实现方式,通常链式调用

  • 详解JavaScript Promise和Async/Await

    概述 一般在开发中,查询网络API操作时往往是比较耗时的,这意味着可能需要一段时间的等待才能获得响应.因此,为了避免程序在请求时无响应的情况,异步编程就成为了开发人员的一项基本技能. 在JavaScript中处理异步操作时,通常我们经常会听到 "Promise "这个概念.但要理解它的工作原理及使用方法可能会比较抽象和难以理解. 四个示例 那么,在本文中我们将会通过实践的方式让你能更快速的理解它们的概念和用法,所以与许多传统干巴巴的教程都不同,我们将通过以下四个示例开始: 示例1:用生

  • 详解JavaScript私有类字段和TypeScript私有修饰符

    JavaScript私有类字段和隐私需求 在过去,JavaScript 没有保护变量不受访问的原生机制,当然除非是典型闭包. 闭包是 JavaScript 中许多类似于私有模式(如流行的模块模式)的基础.但是,近年来 ECMAScript 2015 类被使用后,开发人员感到需要对类成员的隐私进行更多控制. 类字段提案(在撰写本文时处于第 3 阶段)试图通过引入私有类字段来解决问题. 让我们看看它们是什么样子的. 一个 JavaScript 私有类字段的例子 这是一个带有私有字段的 JavaScr

  • 详解javascript中的Strict模式

    简介 在ES5中,引入了strict模式,我们可以称之为严格模式.相应的sloppy mode就可以被称为非严格模式. 严格模式并不是非严格模式的一个子集,相反的严格模式在语义上和非严格模式都发生了一定的变化,所以我们在使用过程中,一定要经过严格的测试.以保证在严格模式下程序的执行和非严格模式下的执行效果一致. 使用Strict mode strict mode会改变javascript的一些表现,我们将会在下一节中进行详细的讲解. 这里先来看一下,怎么使用strict mode. Strict

  • 详解JavaScript引擎V8执行流程

    目录 一.V8来源 二.V8的服务对象 三.V8的早期架构 四.V8早期架构的缺陷 五.V8的现有架构 六.V8的词法分析和语法分析 七.V8 AST抽象语法树 八.字节码 九.Turbofan 一.V8来源 V8的名字来源于汽车的"V型8缸发动机"(V8发动机).V8发动机主要是美国发展起来,因为马力十足而广为人知.V8引擎的命名是Google向用户展示它是一款强力并且高速的JavaScript引擎. V8未诞生之前,早期主流的JavaScript引擎是JavaScriptCore引

  • 详解JavaScript中Arguments对象用途

    目录 前言 Arguments 的基本概念 Arguments 的作用 获取实参和形参的个数 修改实参值 改变实参的个数 检测参数合法性 函数的参数个数不确定时,用于访问调用函数的实参值 遍历或访问实参的值 总结 在实际开发中,Arguments 对象非常有用.灵活使用 Arguments 对象,可以提升使用函数的灵活性,增强函数在抽象编程中的适应能力和纠错能力. JavaScript 中 Arguments 对象的用途总结. 前言 相信我们很多人在代码开发的过程中都使用到过一个特殊的对象 --

随机推荐