当前位置: 首页 > news >正文

前端中 try-catch 捕获不到哪些异常和常见错误

在开发过程中,我们的目标是 0error,0warning

但有很多因素并不是我们可控的,为了避免某块代码的错误,影响到其他模块或者整体代码的运行,我们经常会使用try-catch模块来主动捕获一些异常或者错误。

比如我们在获取 url 中的参数后,对其进行 JSON 解析,这里就要用try-catch包裹一下,因为我们不能保证获取到的参数一定是可以正常解析的:

const user= getQueryString('user');
if (user) {try {const { id, username} = JSON.parse(user);console.log(id, username);} catch (err) {console.error(err);}
}

用户在复制链接的过程中,有可能会有意无意地复制不完全,导致整个参数不完整,JSON.parse无法解析不完整的 json string。为了避免因数据不完整造成的 JSON 解析错误,我们可以将其用try-catch包括起来。

一、 try-catch 不能捕获哪些错误

我们经常会使用try-catch模块来主动捕获一些异常或者错误,避免此块的代码影响到其他模块或者整体代码的运行。但有些情况,try-catch 并不能捕获到代码中的异常!

1.跨域的错误

当我们使用 xhr 请求接口,若接口不支持跨域时,浏览器会在控制台提示错误:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>trycatch演示</title><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.js"></script>
</head><body><button onclick="cli()">点我</button><script>function cli() {try {$.get('http://www.baidu.com', function success(data) {console.log(data)})} catch (e) {console.log(e)}}</script>
</body></html>
Access to XMLHttpRequest at 'https://www.baidu.com/' (redirected from 'http://www.baidu.com/') from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

通过图片中我们可以看到,请求接口时产生了跨域错误,但并没有进入到catch中。我们通过 xhr.onerror 的监听,是可以知道 xhr 请求产生了请求错误的。
在这里插入图片描述

2.异步错误

try 中异步的模块产生了错误,catch 也是捕获不到的,例如:

// setTimeout中的错误
try {setTimeout(function () {throw new Error('error in setTimeout'); // 200ms后会把异常抛出到全局}, 200);
} catch (err) {console.error('catch error', err); // 不会执行
}

在这里插入图片描述

// Promise中的错误
try {Promise.resolve().then(() => {throw new Error('error in Promise.then');});
} catch (err) {console.error('catch error', err);

在这里插入图片描述
从运行结果可以看到,这两种代码,均没有进入到 catch 模块中。

为什么没有进入到catch模块中呢?
当异步函数抛出异常时,对于宏任务而言,执行函数时已经将该函数推入栈,此时并不在 try-catch 所在的栈,所以 try-catch 并不能捕获到错误。对于微任务而言,比如 promise,promise 的构造函数的异常只能被自带的 reject 也就是.catch 函数捕获到。

捕获异步的错误
答案就是把 try-catch 放到异步代码的里面。

1.将try-catch放到setTimeout内部

// 将try-catch放到setTimeout内部
setTimeout(() => {try {throw new Error('error in setTimeout');} catch (err) {console.error('catch error', err);}
}, 200);

在这里插入图片描述
2.将try-catch放到then内部

// 将try-catch放到then内部
Promise.resolve().then(() => {try {throw new Error('error in Promise.then');} catch (err) {console.error('catch error', err);}
});

在这里插入图片描述

3.使用Promse自带的catch捕获异常

// 使用Promse自带的catch捕获异常
Promise.resolve().then(() => {throw new Error('error in Promise.then');}).catch((err) => {console.error('Promise.catch error', err);
});

在这里插入图片描述
Promise 有一个很大的优势是,它自带着异常捕获方法catch(),在 then()方法产生错误导致代码无法运行时,会自动进入到 catch()方法中。因此建议写 Promise 时,都把 catch()写上,否则未捕获的异常,就会冒泡到全局。

3.async-await 的异常如何捕获

await可与.catch()同时使用。try/catch 能捕获所有异常, .catch只能捕获异步方法中reject错误

也就是说,如果只想捕获 异步方法中reject错误的话,在使用await的同时使用.catch()就能捕获到。但捕获不到reject之外的异常。

如下图:

1.同时使用捕获到了reject异常:

const foo=()=>{return new Promise((resolve, reject) => {throw new Error('throw 错误')});}
await foo().catch(e=>{console.log('捕获到了:'+e)});

在这里插入图片描述

2.捕获不到reject之外的异常,直接报错:
(这种情况就需要使用try/catch捕获处理了)

 const foo=()=>{throw new Error('throw 错误');return new Promise((resolve, reject) => {resolve('resolve 错误')});}
await foo().catch(e=>{console.log('捕获到了:'+e)});

在这里插入图片描述
但这种捕获异常后,外层的 catch()方法就捕获不到异常了,不再继续向外层冒泡了。正确的做法是,底层模块产生的错误,应当直接抛出给业务层,让业务层决定这个错误怎么处理,而不是直接吞掉。

4.多层 try-catch

多层 try-catch 时,会被最内层的 catch()方法捕获到,然后就不再向外层冒泡:

try {try {throw new Error('error');} catch (err) {console.error('内层的catch', err); // 内层的catch Error: error}
} catch (err) {console.error('最外层的catch', error);
}

在这里插入图片描述

js 中出现的错误类型。

在了解使用try-catch之前,我们先来了解下 js 中有哪些个原生的错误类型。

js 代码在运行时可能产生的错误错误共有 6 种类型:

  1. 语法错误(SyntaxError);
  2. 类型错误(TypeError);
  3. 范围错误(RangeError);
  4. eval 错误(EvalError);
  5. 引用错误(ReferenceError);
  6. URI 错误(URIError);

这些错误类型都继承自Error类。

1、语法错误(SyntaxError

语法错误,通常是开发者在开发过程,代码语句写的有问题,浏览器无法对其进行解析:

const a=;

错误信息:

VM202:1 Uncaught SyntaxError: Unexpected token ';'

2、类型错误(TypeError);

类型错误通常会出现在两种情况:

  • 操作符使用在了不适当的类型变量上,例如对数字类型使用 concat 操作;
  • 操作的变量遇到不可预期的 null 或者 undefined 值:
const obj = {};
obj.concat([1]);

错误信息

VM211:2 Uncaught TypeError: obj.concat is not a functionat <anonymous>:2:5

在这里插入图片描述

const a = null;
a.nickname; //VM218:2 Uncaught TypeError: Cannot read properties of null (reading 'nickname')at <anonymous>:2:3

在编写一些方法供给其他模块调用时,当在检查到参数传入为空或者 null等空置时,可以抛出TypeError的错误。

3、范围错误(RangeError);

该错误通常是因为传入的参数,超出了规定的范围。例如toFixed()方法可以接受 0-100 范围内的数值,当超过这个范围时,就会抛出该错误。

Math.PI.toFixed(105); // Uncaught RangeError: toFixed() digits argument must be between 0 and 100

在这里插入图片描述

4、eval 错误(EvalError);

这种错误一般很少会遇到,因为使用 eval 操作时,即使不正当的错误,也会抛出其他类型的错误。

new eval(); // Uncaught TypeError: eval is not a constructor
eval = 1234; // 正确执行

在这里插入图片描述

5、引用错误(ReferenceError);

引用错误表示师徒访问一个未经声明的变量:

console.log(nick); // Uncaught ReferenceError: nick is not defined

在这里插入图片描述

6、URI 错误(URIError);

该错误通常是一些操作 uri 函数抛出的错误,主要包括:encodeURI(), decodeURI(), encodeURIComponent(), decodeURIComponent(), escape(), unescape()

decodeURIComponent('%'); // Uncaught URIError: URI malformed
decodeURIComponent('%23'); // # 正确执行

在这里插入图片描述

在这里插入图片描述

自定义错误类型

对于稍微大点的模块,我们想自定义一些错误类型,通过这些错误类型,就能看出是某个模块抛出的错误。该怎么写呢?

我们自定义的错误类型也是要继承自Error类的,实现起来非常简单:

class FingerError extends Error {constructor(message) {super(message);this.name = 'FingerError'; // 该错误的名称Error.captureStackTrace(this, this.constructor); // 获取错误堆栈的信息}
}const err = new FingerError('get name error');
console.error(err); // FingerError: get name error
err instanceof FingerError; // true

在这里插入图片描述

总结

前端中还有很多种产生错误的方式的,我们平时就要注意避免这些错误。我们接下来也可以从错误监控的角度来分析下,如何来监控页面中出现的错误和错误类型。

相关文章:

前端中 try-catch 捕获不到哪些异常和常见错误

在开发过程中&#xff0c;我们的目标是 0error&#xff0c;0warning。 但有很多因素并不是我们可控的&#xff0c;为了避免某块代码的错误&#xff0c;影响到其他模块或者整体代码的运行&#xff0c;我们经常会使用try-catch模块来主动捕获一些异常或者错误。 比如我们在获取…...

javaEE 初阶 — 如何构造一个 HTTP 请求

文章目录使用 form 表单标签构造1 构造 GET 请求2 构造 POST 请求使用 ajax 构造1 什么是异步2 代码中如何使用 ajax使用第三方工具构造1 postman 工具的安装2 postman 工具的使用使用 form 表单标签构造 1 构造 GET 请求 使用 form 表单构造 HTTP 请求&#xff0c;需要用到两…...

CentOS 7下安装PostgreSQL 15版本数据库(图文详细)

文章目录CentOS 7下安装PostgreSQL 15版本数据库(图文详细)1 简介1.1 概述1.2 官网2 PostgreSQL安装2.1 选定版本2.2 安装依赖2.3 执行安装2.4 初始化2.5 配置环境变量2.6 创建数据库2.6.1 进入命令行2.6.2 创建DB2.6.3 设置密码2.7 配置远程2.8 测试链接3 pgAdmin4工具安装3.1…...

代码随想录算法训练营第五十一天 | 309. 最佳买卖股票时机含冷冻期、714. 买卖股票的最佳时机含手续费

309. 最佳买卖股票时机含冷冻期 动规五部曲 1、确定dp数组以及下标的含义 dp[i][j]&#xff0c;第i天状态为j&#xff0c;所剩的最多现金为dp[i][j]。 具体可以区分出如下四个状态&#xff1a; 状态一&#xff1a;持有股票状态&#xff08;今天买入股票&#xff0c;或者是…...

中英文拼写检测纠正开源项目使用入门 word-checker 1.1.0

项目简介 word-checker 本项目用于单词拼写检查。支持英文单词拼写检测&#xff0c;和中文拼写检测。 特性说明 可以迅速判断当前单词是否拼写错误 可以返回最佳匹配结果 可以返回纠正匹配列表&#xff0c;支持指定返回列表的大小 错误提示支持 i18n 支持大小写、全角半角…...

面试如果还不会Netty,看这篇文章就够了

我们去面试的时候&#xff0c;经常被问到netty的题目。我整理了netty的32连问。小伙伴们&#xff0c;收藏起来慢慢看吧。 1. Netty是什么&#xff0c;它的主要特点是什么&#xff1f; Netty是一个高性能、异步事件驱动的网络编程框架&#xff0c;它基于NIO技术实现&#xff0…...

作为大学生,你还不会搭建chatGPT微应用吗?

目录 引言ChatGPT是什么&#xff1f;背景&#xff1a;ChatGPT敢为人先&#xff0c;打破全球僵局示例演示&#xff1a;基于ChatGPT微应用实现的条件及步骤&#xff08;1&#xff09;整体框架&#xff08;2&#xff09;搭建前的准备工作&#xff08;3&#xff09;实际搭建步骤&a…...

Three.js教程:第一个3D场景

推荐&#xff1a;将NSDT场景编辑器加入你3D工具链其他工具系列&#xff1a;NSDT简石数字孪生下面的代码完整展示了通过three.js引擎创建的一个三维场景&#xff0c;在场景中绘制并渲染了一个立方体的效果&#xff0c;为了大家更好的宏观了解three.js引擎&#xff0c; 尽量使用了…...

lua快速入门~在js基础上,知道Lua 和 Js 的不同即可

☺ lua 和 javaScript 差不多的&#xff0c;就是一些语法的细节不同&#xff0c;学过js&#xff0c;再注意一下下面的细节&#xff0c;就能上手了~ 快速入门&#xff0c;可以直接看一下菜鸟教程的lua&#xff1a;https://www.runoob.com/lua/lua-tutorial.html Lua 和 Js 的不同…...

Linux系统【Centos7】更换源详细教程

更换CentOS 7系统的源可以提高网络速度&#xff0c;加快软件升级和安装的速度。以下是详细的更换CentOS 7源实践。 步骤 1&#xff1a;备份原始 Yum.repo 在更换之前&#xff0c;首先要备份原始 Yum.repo 文件&#xff08;一定要记得备份&#xff09;。 bash sudo mv /etc/y…...

金三银四求职季来了!分享几道最常见的app面试题,帮助您更好准备面试求职!

目录&#xff1a;导读 引言 一、Web 端测试和 App 端测试有何不同? 二、App是如何测试的&#xff1f; 三、app闪退的可能原因&#xff1f; 四、给你一个登录页面,你要如何测试&#xff1f; 五、测试过程中遇到app出现crash或者ANR&#xff0c;你会怎么处理&#xff1f; …...

Java集合——List接口学习总结

一、ArrayList实现类 1. 常用方法 增加&#xff1a;add(int index, E element)删除&#xff1a;remove(int index) remove(Object o)修改&#xff1a;set(int index, E element)查看&#xff1a;get(int index)判断&#xff1a;常用遍历方式&#xff1a;//List集合 遍历&…...

低代码(三)低代码平台前端技术组件选型1.0(前端)

目前国内主流的低代码开发平台有&#xff1a;金蝶、用友、宜搭、云程、简道云、明道云、氚云、伙伴云、道一云、JEPaaS、华炎魔方、搭搭云、JeecgBoot 、RuoYi等。这些平台各有优劣势&#xff0c;定位也不同&#xff0c;用户可以根据自己需求选择。如果企业想自主可控&#xff…...

代码随想录算法训练营第35天|860.柠檬水找零,406.根据身高重建队列,452. 用最少数量的箭引爆气球

代码随想录算法训练营第35天|860.柠檬水找零&#xff0c;406.根据身高重建队列&#xff0c;452. 用最少数量的箭引爆气球860.柠檬水找零406. 根据身高重建队列452. 用最少数量的箭引爆气球860.柠檬水找零 题目链接&#xff1a;860.柠檬水找零&#xff0c;难度&#xff1a;简单…...

C++整人代码,十分朴实但威力无穷,让你对cout怀疑人生,整死你的同学

cout人人皆知 /a 只是让电脑响个铃 直接上个简单的代码 #include<iostream> using namespace std; int main() {while(1)cout<<"\a"; }最后普及一下&#xff1a; 控制符的作用有&#xff1a; setbase(n) 以n进制方式输出(n8,10,16) setfill(ch) 设置…...

【Spring Cloud Alibaba】12.定时任务(xxl-job)

文章目录简介什么是xxl-job调度中心执行器官方架构图相关地址环境要求配置调度中心下载源码目录说明初始化数据库源码方式docker方式测试集群&#xff08;可选&#xff09;配置执行器pom.xmlapplication.propertiesXxlJobExecutorApplication.java执行器组件配置创建定时任务任…...

GDB core dump分析

基本知识 Linux core dump&#xff1a;一般称之为核心转储、内核转储&#xff0c;我们统称为转储文件。是某个时刻某个进程的内存信息映射&#xff0c;即包含了生成转储文件时该进程的整个内存信息以及寄存器等信息。转储文件可以是某个进程的&#xff0c;也可以是整个系统的。…...

Leetcode.111 二叉树的最小深度

题目链接 Leetcode.111 二叉树的最小深度 easy 题目描述 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从 根节点 到 最近叶子节点 的 最短路径上的节点数量。 说明: 叶子节点是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,nul…...

【RP-RV1126】SDK编译常用记录

文章目录一、单独编译1.1 单独配置编译kernel1.2 单独编译配置Buildroot1.3 单独编译rkmedia1.3.1 添加自己的rkmedia代码文件荣品的RV1126。一、单独编译 如果执行 build.sh 运行完成后没有在 rockdev/ 目录下生成镜像文件&#xff0c;请执行&#xff1a; ./build.sh firmwa…...

【操作系统复习】第5章 存储器管理

存储器的层次结构 存储层次 ➢ CPU寄存器 ➢ 主存&#xff1a;高速缓存、主存储器、磁盘缓存 ➢ 辅存&#xff1a;固定磁盘、可移动介质 层次越高&#xff0c;访问速度越快&#xff0c;价格也越高&#xff0c;存储容量也最小 寄存器和主存掉电后存储的信息不再存在&a…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...