[Summary] 1574- An article discusses the principle of front-end exceptions in detail

pingan8787 2023-01-25 20:26:34 阅读数:779

summary1574-articlediscussesprinciple

ee523dc5d33daba80a9ca59835e85bd7.jpeg

作者介绍:@邹鹏,58 同城资深前端工程师,负责 58 The local growth business,58 Beidou monitoring platform core members,Committed to the front-end engineering,The front-end monitoring field.

导读

As the front-end monitoring system construction in recent years, increasingly perfect,Front-end engineers to abnormal pay more attention to.业界关于 JS Introduced only talked mostly anomaly capture method,The causes and treatment method of talk less.This paper will detail exception principle,The author in recent 2 Years in the field of the front-end monitoring to deal with the exception of experience to share with everyone.

fa1bca989ce030127fe80b7d7b273ba2.jpeg

异常定义

异常,Exception, The unexpected events,在程序执行过程中发生,Will interrupt normal program run.

d5aa0c021e087bfbdeffc200b8ded26e.png

ECMA-262 白皮书 13 版中描述了 8 种异常

  • SyntaxError:语法异常

  • ReferenceError:引用异常

  • RangeError:范围异常

  • Error:异常基类

  • InternalError:内部异常

  • TypeError: 类型异常

  • EvalError: Eval 方法异常

  • URIError: URI Relevant methods to produce abnormal

1. SyntaxError

Before the engine to execute code,编译器需要对 js 进行编译,Edit stage includes:词法分析,语法分析;如图:

0b5fae5a87b45576c3b695304061899b.png

Compile phase of exceptions are SyntaxError,但 SyntaxError Don't completely have occurred in the compile phase;

const a = '3;

比如这行代码,The lack of a quote,就会发生: SyntaxError: Invalid or unexpected token.

其他常见的 SyntaxError:

  • SyntaxError:Unexpected token u in JSON at position 0

  • SyntaxError:Unexpected token '<'

  • SyntaxError:Unexpected identifier

绝大部分 SyntaxError Can check through configuration editor tool,During the development phase to avoid any.

2. ReferenceError

引用异常,比较常见,类似于 Java Language is one of the most famous null pointer exception (Null Pointer Exception,NPE).

  • ReferenceError:$ is not defined

  • ReferenceError:Can't find variable: $

上面举的 2 A case reference exception is actually the same exception,第一个是发生在 Android,第二个是在 iOS 下,异常对象的 message With the difference of compatibility.

What circumstance under meeting occurrence reference exception?

这里需要先提一下 LHS 查询和 RHS 查询.

比如 const a = 2; ,对于这一行代码,引擎会为变量 a 进行 LHS 查询.另外一个查找的类型叫作 RHS,In the assignment statement Left Hand Side 和 Right Hand Side.RHS 查询与简单地查找某个变量的值别无二致,而 LHS 查询则是试图找到变量的容器本身,即作用域.

LHS 和 RHS 的含义是 “赋值操作的左侧或右侧” 并不一定意味着就是 “=”.比如 console.log(a) Also will be abnormal RHS.我们再来看一个例子:

function foo(a) {
var b = a;
return a + b;
}
var c = foo(2);

其中有 function foo;Var c;A = 2;Var b 这 4 次 LHS 和 4 次 RHS

为什么区分 LHS 和 RHS 是一件重要的事情?

Because in the case of variable has not been declared,这两种查询的行为是不一样的.

如果 RHS 查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出 ReferenceError.

如果 RHS 查询找到了一个变量,但是你尝试对这个变量的值进行不合理的操作,Throw another type of exception,叫作 TypeError.

3. TypeError

TypeError In the values for unreasonable operation happens,比如试图对一个非函数类型的值进行函数调用,或者引用 null 或 undefined 类型的值中的属性,Then the engine will throw out this type of exception.比如:

TypeError:Cannot read property 'length' of undefined

This is one of the most common abnormal,In judging can happen when the array length.

Can do precondition to empty,比如:

if (obj) {
res = obj.name;
}

Can also be rewritten into a logical and arithmetic && 的表达式写法

res = obj && obj.name;

But if the property is more,This method is very ugly,Can use the optional chain writing,如下:

res = obj && obj.a && obj.a.b && obj.a.b.name
res = obj?.a?.b?.name;

Although the condition judgment、逻辑与判断、Optional chain judgment can avoid error,但是还是有 2 个缺点:

  • js For variable Bool The casting method is not rigorous,Possible judgment

  • This writing at the time of empty bank code won't error,But subsequent logic might have a problem;Just reduce the abnormal,And there's no way to solve this situation.Recommended for important logic code try/catch 来处理,May, when necessary, plus logs to analysis.

4. RangeError

范围错误,比如:

  • new Array(-20) 会导致 RangeError: Invalid array length

  • Memory consumption such as recursive program will lead to RangeError: Maximum call stack size exceeded

Recursion can use a loop + Stack or tail recursive way to optimize

//普通递归
const sum = (n) => {
if (n <= 1) return n;
return n + sum(n-1)
}
//尾递归
const sum = (n, prevSum = 0) => {
if (n <= 1) return n + prevSum;
return sum(n-1, n + prevSum)
}

尾递归和一般的递归不同在对内存的占用,普通递归创建 stack 累积而后计算收缩,尾递归只会占用恒量的内存.当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的.

5. Error 与自定义异常

Error 是所有错误的基类,其他错误类型继承该类型.All of the wrong type share the same properties.

  • Error.prototype.message 错误消息.For the user to create Error 对象,This is the first parameter to the constructor provides a string.

  • Error.prototype.name 错误名称.This is determined by the constructor.

  • Error.prototype.stack 错误堆栈

通过继承 Error Can also create custom error type.Create a custom error type,需要提供 name 属性和 message 属性.

class MyError extends Error {
constructor(message) {
super();
this.name = 'MyError'
this.message = message }
}

Most popular frameworks will encapsulate some custom exception,比如 Axios 和 React.

React 在 ErrorDecoder In the module to introduce our custom error.Every mistake ID,比如 ID:185 错误是:在 componentDidUpdate 函数中调用了 this.setState() 方法,导致 componentDidUpdate 陷入死循环.After an error in the output log with abnormal referral link.

https://reactjs.org/docs/error-decoder.html/?invariant = 异常 ID.

Using the links open visual link,如下:

5d942687da720cd6f961adc3003405f2.jpeg

6. Error: Script Error.

它是 Error Type one of the most common;Because there is no specific exception stack and code number,Become one of the most mysterious anomaly can be.

Due to the browser based on safety effect to avoid sensitive information inadvertently by a third party (不受控制的) 脚本捕获到,浏览器只允许同域下的脚本捕获具体的错误信息.

但大部分的 JS 文件都存放在 CDN 上面,Do not match the domain name with the page.To do abnormal monitoring can only capture Error: Script Error. Can't capture stack and accurate information.2 步解决:

1、给 script 标签增加 crossorigin 属性,让浏览器允许页面请求资源.

<scrpit src="http://def.com/demo.js" crossorigin="anonymous"></script>

Such request header sec-fetch-mode 值就会变成 cors, 默认是 no-cors.

But some of the browser is not compatible with this method,加上 crossorigin Still can't send sec-fetch-mode:cors 请求

2、To static resource server response header to allow cross-domain tag.

Access-Control-Allow-Origin: *.58.com

大部分主流 CDN 默认添加了 Access-Control-Allow-Origin 属性.

The whole process can refer to the following flow chart:

7c361cd07edf1bd52ed26bfa51971956.png

Combined with cross-domain request header、After the response headers may still have a lot of ScriptError,Consider the following situation

  • 通过 append Script 标签异步加载 JS

  • JSONP 请求

  • 第三方 SDK

7. 其他异常

InternalError

This is a rare exception,在 JS 引擎内部发生,Example scenario is usually some ingredients too,例如:

  • “too many switch cases”(过多 case 子句);

  • “too many parentheses in regular expression”(正则表达式中括号过多);

  • “array initializer too large”(数组初始化器过大);

EvalError

在 eval() The execution of a method throws EvalError 异常.

根据 Ecma2018 版以后,This exception will no longer be thrown,但是 EvalError 对象仍然保持兼容性.

URIError

Used in a wrong way to use the global URI 处理函数而产生的错误.

decodeURI, decodeURIComponent, encodeURI, encodeURIComponent These four methods will produce this abnormal;

比如执行 decodeURI('%%') 的异常:Uncaught URIError: URI malformed

异常处理

ECMA-262 第 3 版新增了 try/catch 语句,作为在 JavaScript 中处理异常的一种方式.基本的语法如下所示,跟 Java 中的 try/catch 语句一样.

1. finally

finally 在 try-catch 语句中是可选的,finally 子句一经使用,其代码无论如何都会执行.

function a () {
try {
return '约会'
} catch (e) {
return 'Date of failure'
} finally {
return '睡觉';
}
}
console.log('函数结果:', a()) // '睡觉'

上述代码的结果是 ' 睡觉 ',finally 会阻止 return 语句的终止.

2. throw
throw new Error('Boom');

When should a manual throws an exception?

A guiding principle is a predictable process under certain circumstances can not correctly to proceed,Need to tell the caller exception details,Not just the abnormal content itself.比如上文提到的 React 自定义异常;

一个健壮的函数,Type of the parameter effectiveness;Usually in the argument is not reasonable,In order to avoid the error block program is running,Developers will by default value,return Waiting is handled.

This way, although there is no error,The results of application may not be in line with expectations,The default design out ignored cause semantic misunderstanding;另外,Also may not be able to avoid subsequent code error;

3. 断言

Mentioned above can be predicted,很容易联想到 Node 中的断言 assert,如果表达式不符合预期,就抛出一个错误.

assert 方法接受两个参数,当第一个参数对应的布尔值为 true 时,不会有任何提示,返回 undefined.当第一个参数对应的布尔值为 false 时,会抛出一个错误,该错误的提示信息就是第二个参数设定的字符串.

var assert = require('assert');
function add (a, b) {
return a + b;
}
var expected = add(1,1);
assert( expected === 2, '预期1加1等于2');

通常在 TDD 开发模式中,Be used to write the test case;

不过 ECMA No similar design,Interested can encapsulate a simple assert 方法.浏览器环境中的 console Objects have similar assert 方法.

4. Asynchronous exceptions in

Asynchronous code,In the event loop,就无法通过 try catch 到.

主要注意的是,Promise 的 catch 方法用于处理 rejected 状态,Rather than deal with abnormal.Rejected State unprocessed words will trigger Uncaught Rejection. The latter can be unified through the following ways to monitor.

window.onunhandledrejection = (event) => {
console.warn(`REJECTION: ${event.reason}`);
};

tips: await 这种 Promise 的同步写法,Often overlooked by developers rejected 的处理,可以用 try catch 来捕获.

5. 异常监控

The service side usually abnormal monitoring through server logs,Such as observation of single server log output,或 kibana 可视化查询.
The biggest difference between the front-end of abnormal monitoring and,Is the need of the abnormal data the client through the network to collect.

Use the following several ways to collect data:

  • window.onerror Catch exceptions grammar

  • 可以重写 setTimeout、setInterval 等异步方法,With synchronous writing try To capture the error in an asynchronous function

  • window.addEventListener (‘unhandledrejection’,・・・); Capture pending asynchronous reject

  • window.addEventListener (‘error’, …) Catch exceptions resources

  • 重写 fetch, XMLHttpRequest To capture the interface state

总结

本文详细讲解了 ECMA 中 8 Kind of exception principle,涉及了 LHS&RHS、递归优化、ScriptError、finally、Promise 等知识点,Hope in the treatment of the abnormal work can bring you help.

参考

  • ecma-262: https://www.ecma-international.org/publications-and-standards/standards/ecma-262/

  • ES6th 白皮书: https://262.ecma-international.org/6.0

  • React Error Decoder: https://reactjs.org/docs/error-decoder.html/?invariant=1

  • 《Js 高级程序设计 第四版》

  • 《你不知道的 JS》

往期回顾
#如何使用 TypeScript 开发 React 函数式组件?
#11 个需要避免的 React 错误用法
#6 个 Vue3 开发必备的 VSCode 插件
#3 款非常实用的 Node.js 版本管理工具
#6 个你必须明白 Vue3 的 ref 和 reactive 问题
#6 个意想不到的 JavaScript 问题
#试着换个角度理解低代码平台设计的本质
版权声明:本文为[pingan8787]所创,转载请带上原文链接,感谢。 https://qdmana.com/2023/025/202301252011259679.html